爬虫

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

 

原文地址:https://www.cnblogs.com/dingxingxing/p/13539453.html