zoukankan      html  css  js  c++  java
  • 爬虫

    cheerio

    简介:

    cheerio是node.js的抓取页面模块,为服务器特别定制的,快速、灵活、实施的jQuery核心实现。适合各种web爬虫程序。

    cheerios官网

    爬取斗图啦网站图片例子

     
     1 const cheerio = require('cheerio')
     2  const axios = require('axios')
     3  const fs = require('fs')
     4  const path = require('path')
     5  // cheerio 获取HTML文档的内容,内容的获取跟jquery一样
     6  7  // 起始地址-分析网站结构
     8  let httpUrl = "https://www.doutula.com/article/list/?page=1";
     9 10  // 获取页面总数
    11  async function getNum() {
    12    res = await axios.get(httpUrl)
    13    let $ = cheerio.load(res.data)
    14    let btnLength = $('.pagination li').length
    15    let allNum = $('.pagination li').eq(btnLength - 2).find('a').text()
    16    console.log(allNum);
    17    return allNum
    18  }
    19 20  async function spider() {
    21    // 获取所有页面的总数
    22    let allPageNum = await getNum()
    23    for(let i=1;i<= 50;i++) {
    24      getListPage(i)
    25    }
    26  }
    27 28  async function getListPage(pageNum) {
    29    let httpUrl = "https://www.doutula.com/article/list/?page=" + pageNum;
    30    let res = await axios.get(httpUrl)
    31    // cheerio解析html文档
    32    let $ = cheerio.load(res.data)
    33    // 获取当前页面的所有的表情页面的链接
    34    $('#home .col-sm-9>a').each((i, element) => {
    35      let pageUrl = $(element).attr('href')
    36      let title = $(element).find('.random_title').text()
    37      let reg = /(.*?)d/igs;
    38      title = reg.exec(title)[1]
    39      fs.mkdir(`./img/${title}`, (err) => {
    40        if (err) {
    41          console.log(err);
    42        } else {
    43          console.log('成功创建目录:' + './img/' + title);
    44        }
    45      })
    46      parsePage(pageUrl, title)
    47    })
    48  }
    49 50  async function parsePage(url, title) {
    51    let res = await axios.get(url)
    52    let $ = cheerio.load(res.data)
    53    $('.pic-content img').each((i, element) => {
    54      let imgUrl = $(element).attr('src')
    55      // 获取扩展名
    56      let extName = path.extname(imgUrl)
    57      // 图片写入的路径和名字
    58      let imgPath = `./img/${title}/${title}-${i}${extName}`
    59      // 创建图片可写流
    60      let ws = fs.createWriteStream(imgPath)
    61      axios.get(imgUrl, { responseType: 'stream' }).then(res => {
    62        // 通过管道流入到可写流的来源流
    63        res.data.pipe(ws)
    64        console.log('图片加载完成:', imgPath);
    65        // res.data.on('close',() => {
    66        //   ws.close()
    67        // })
    68      })
    69    })
    70  }
    71  spider()

     

    爬取音乐网站下载音乐:

     
     1 // 目标:下载音乐
     2  // 1获取音乐相关的信息,通过音乐相关的信息获取mp3地址
     3  // 2如何获取大量的音乐信息,通过获取音乐列表
     4  // 3通过音乐的分类页,获取音乐列表
     5  6  const axios = require('axios')
     7  const fs = require('fs')
     8  const path = require('path')
     9 10  // 获取音乐
    11  async function getPage(num) {
    12    let httpUrl = "http://www.app-echo.com/api/recommend/sound-day?page=" + num
    13    let res = await axios.get(httpUrl)
    14 15    res.data.list.forEach((item, i) => {
    16      let title = item.sound.name
    17      let mp3Url = item.sound.source
    18      let filename = path.parse(mp3Url).name
    19 20      let content = `${title},${mp3Url},${filename}
    `
    21      fs.writeFile('music.txt', content, {flag:'a'},() => {
    22        console.log('写入完成:'+ title);
    23      })
    24      // console.log(title);
    25      // console.log(mp3Url);
    26      download(mp3Url,filename)
    27    })
    28  }
    29 30  // 下载音乐
    31  async function download(mp3Url, filename) {
    32    let res = await axios.get(mp3Url, { responseType: "stream" })
    33    // 创建可写流
    34    let ws = fs.createWriteStream('./mp3/' + filename + '.mp3')
    35    // 通过管道流入到可写流的来源流
    36    res.data.pipe(ws)
    37    // res.data.on('close',() => {
    38    //   ws.close()
    39    // })
    40  }
    41 42  for(i=1;i<=5; i++) {
    43    getPage(i)
    44  }

     

    Puppeteer

    出现的背景

    Chrome59(linux、macos)、Chrome60(windows)之后,Chrome自带headless(无界面)模式很方便做自动化测试或者爬虫。但是如何和headless模式的Chrome交互则是一个问题。通过启动Chrome时的命令参行参仅能实现简易的启动时初始化操作。Selenium、Webdriver等是一种解决方案,但是往往依赖众多,不够扁平。

    Puppteer是谷歌官方出品的一个通过DevTools协议控制headless Chrome的库。通过Puppeteer的提供api直接控制Chrome模拟大部分用户操作来进行UI Test或者作为爬虫访问页面来收集数据。

    作用:

    • 生成页面的屏幕截图和PDF。

    • 爬取SPA(单页应用程序)并生成预渲染的内容(即“ SSR”(服务器端渲染))。

    • 自动化表单提交,UI测试,键盘输入等。

    • 创建最新的自动化测试环境。使用最新的JavaScript和浏览器功能,直接在最新版本的Chrome中运行测试。

    • 捕获站点的时间线跟踪以帮助诊断性能问题。

    • 测试Chrome扩展程序。

    使用和例子

    Puppeteer类似其他框架,通过操作Browser实例来操作浏览器做出相应的反应。

     
     1 const puppeteer = require('puppeteer')
     2  3  (async () => {
     4      const browser = await puppeteer.launch();
     5      const page = await browser.newPage();
     6      await page.to('http://rennaiqian.com');
     7      await page.screenshot({path:'example.png'});
     8      await page.pdf({path:'example.pdf',format:'A4'});
     9      await browser.close()
    10  })()

    上述代码通过puppeteer的launch方法生成了一个browser的实例,对应于浏览器,launch方法可以传入配置选项,比较有用的是在本地调试时传入{headless:false}可以关闭headless模式。

    1  const browser = await puppeteer.launch({headless: false})

    browser.newPage方法可以打开一个新选项卡并返回选项卡的实例page,通过page上的各种方法可以对页面进行常用操作。上述代码就进行了截屏和打印pdf的操作。

     

    爬虫总结

    1.爬虫介绍

    通过模拟浏览器的请求,服务器根据我们的请求返回我们想要的数据,将数据解析出来,并且进行保存

    2.爬虫流程

    1-目标:确定你想要获取的数据

    1. 确定想要的数据在什么页面

    2. 确定在哪些页面可以链接到这些页面

    3. 寻找页面之间和数据之间的规律

       

      2-分析页面

    4. 获取数据的方法(正则,cherrio)

    5. 分析数据是通过ajax请求的数据,还是html里自带的数据

    6. 如果是通过AjAX请求的数据,那么需要获取ajax请求的链接,一般请求到的数据都为JSON格式数据,那么就容易解析

    7. 如果数据在HTML里面,那么就用cherrio通过选择器将内容选中

       

      3-编写单个数据获取的案例

    8. 解析出分类页的链接地址

    9. 解析出列表页的链接地址

    10. 解析出详情页的链接地址

    11. 解析详情页里面想要获取的数据

    12. 将数据进行保存到本地或者是数据库

       

      4-如果遇到阻碍进行反爬虫对抗

    13. User-Agent是否是正常浏览器的信息

    14. 将请求头设置成跟浏览器一样的内容

    15. 因为爬虫的爬取速度过快,会导致封ip。1那么可以降低速度进行解决,2可以使用代理进行解决

    16. 如果设置需要凭证,那么可以采用无界面浏览器真实模拟。

     

    3.请求数据的库

    request,axiso:通过库,帮助我们快速实现HTTP请求包的打包

    1  request.get('请求地址', {
    2     '请求头字段':'请求头的value值'         
    3  },(res) => { 处理返回的内容 })

    axios优势会更明显,前后端通杀,前后端调用方式一致

     axios.get('请求地址', 参数对象).then((res) => {
         console.log(res)
     })

    axios获取图片

     
    1 axios({
    2      method: 'get',
    3      url: 'http://bit.ly/2mTM3ny',
    4      responseType: 'stream'
    5  })
    6  .then((res) => {
    7      res.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
    8  })

    puppeteer:完全模拟浏览器

    打开浏览器

     1  let options = {
     2      headless: true, // 是否是无界面浏览器
     3      slowMo: 250, // 调试时可以减慢操作速度
     4      defaultViewport: { //设置视宽的宽高
     5           1200
     6          height: 800
     7      },
     8      timeout: 3000, // 默认超时时间3秒
     9  }
    10  let browser = await puppeteer.launch(options)

    打开新标签页

    1  let page = await borwser.newPage()

    获取所有浏览器中的页面

     
    1 let page = await browser.pages()

    关闭浏览器

    1  borwser.close()

    将页面跳转至

    1  await page.goto(url)

    获取页面的对象并进行操作

    1  let btn = await page.$(selector)
    2  let input = await page.$(selector)
    3  // 点击按钮
    4  btn.click()
    5  // 聚焦到输入框
    6  input.forcus()

    在页面上写入内容或者键盘按键

     
    1 await page.keyboard.type('hello World!');
    2  await page.keyboard.press('ArrowLeft');
    3  await page.keyboard.down('Shift');

    截获页面请求

     1  await page.setRequestInterception(true)
     2  page.on('request', request => {
     3      // request 包含请求的所有信息
     4      if(你想要的条件) {
     5          request.continue()
     6      } else {
     7          request.respond({
     8              status: 404,
     9              contentType: 'text/plain',
    10              body: 'Not Found!'
    11          })
    12      }
    13  })

    获取浏览器的信息和内容

    1  page.$eval(selector, (item) => { return item })
    2  page.$$eval(selector, (item) => { return item })

     

    Demo

    GitHub上有:MongoDB数据库+Node爬虫-案例demo,欢迎Clone学习

    更多爬虫相关小案例,欢迎进入github选择"爬虫-Reptiles爬虫"文件夹查看clone

     

  • 相关阅读:
    Darknet 安装
    Spring.Net封闭业务类为WebService注意点和问题
    NHibernate删除数据时遇到deleted object would be re-saved by cascade级联问题
    【不遮遮掩掩】Github上传本地代码以及常见问题解决方案
    Android分享内容和接收分享内容小小实现
    Android v7包下Toolbar和ActionBarActivity实现后退导航效果
    Android MediaPlayer setDataSource failed
    Java入门-类HelloWorld是公共的,应在名为HelloWorld.java的文件中声明
    C#导出Excel文件Firefox中文件名乱码
    【转】如何用css限制文字长度,使溢出的内容用省略号…显示
  • 原文地址:https://www.cnblogs.com/dingxingxing/p/13539453.html
Copyright © 2011-2022 走看看