nodeJS 爬虫,通过Puppeteer实现滚动加载

8,867 阅读2分钟

最近在研究爬虫,所以用自己熟悉的node简单写了一个。

开始用的是phantomjs来获取HTML,但是看了文档之后发现很久没有维护了,所以就放弃了。

后来寻寻觅觅发现了 Puppeteer,看了下是Google开发的,所以果断上手试了试,感觉比phantom不知道高到哪里去了。

B话少说,直接贴项目地址。

github.com/Huoshendame…

项目简介

技术栈

node、puppeteer、cheerio(虽然puppeteer集成了Jq,但是既然已经装了就用一下吧)

安装注意事项

在运行npm install 在安装 puppeteer的时候会报错,因为node下载chrome(puppeteer依赖chrome浏览器)会报错。所以先忽略掉chrome

npm install puppeteer --ignore-scripts

安装成功之后,在去运行

npm install

装好之后,手动吧项目里的 chrome-win 文件夹 放到D盘根目录。

PS:或者你自己放到自己的指定目录,但是在项目里的reptile.js里面 puppeteer.launch的时候需要指定绝对定位的地址

功能介绍

1.通过Puppeteer打开头条新闻页面 www.toutiao.com/ch/news\_ga…

2.获取page实例,通过注入js来实现页面滚动

3.在通过cheerio,分析dom结构,获取标题、图片及链接地址。

4.存储到本地文件。(也可以放到DB里,我这里是直接接口返回了获取的数据,并且顺手存到了本地文件)

源码

/* 引入相关 工具 */
const fs = require('fs')
const cheerio = require('cheerio')
const puppeteer = require('puppeteer')

/* 定义函数 */
let getListData = async function(Category) {
 /* 初始化 puppeteer*/
 const browser = await puppeteer.launch({
  executablePath: 'D:\\chrome-win\\chrome.exe',//把项目中的这个chrome-win文件夹放到D盘根目录
  headless: false //这个是 是否打开chrome可视化窗口 true是不打开 false是打开
 })
 //获取page实例
 const page = await browser.newPage()
 //我这里是通过 入参传过来的 分类来判断抓取相应页面的数据
 let url = ''
 switch (Category) {
  case '0':
   url = 'https://www.toutiao.com/ch/news_game/'
   break;
  case '1':
   url = 'https://www.toutiao.com/ch/news_entertainment/'
   break;
  case '2':
   url = 'https://www.toutiao.com/ch/news_history/'
   break;
  case '3':
   url = 'https://www.toutiao.com/ch/news_finance/'
   break;
 }
 //打开页面
 await page.goto(url)
 //定义页面内容及Jquery
 var content , $
 /* 页面滚动方法 */
 async function scrollPage(i) {
  content = await page.content();
  $ = cheerio.load(content);
  /*执行js代码(滚动页面)*/
  await page.evaluate(function () {
   /* 这里做的是渐进滚动,如果一次性滚动则不会触发获取新数据的监听 */
   for (var y = 0; y <= 1000*i; y += 100) {
    window.scrollTo(0,y)
   }
  })
  // 获取数据列表
  const li = $($('.feedBox').find('ul')[0]).find('li')
  return li
 }
 let i = 0
 let li = await scrollPage(++i)
 //如果数据列表 不够30 则一直获取
 while (li.length < 30) {
  li = await scrollPage(++i)
 }
 let data = {
   list: []
 }
 /* 封装返回的数据*/
 li.map(function (index,item) {
  $(item).find('img').attr('src') != undefined ?
   data.list.push({
    src: $(item).find('img').attr('src'),
    title: $($(item).find('.title')).text(),
    source:$($(item).find('.source')).text(),
    href:$($(item).find('.title')).attr('href')
   }):''
 })
 //顺手存入本地文件
 fs.writeFileSync('tt.JSON',JSON.stringify(data))
 fs.writeFileSync('tt.html',content)
 /* 关闭 puppeteer*/
 await browser.close()
  return data
}
module.exports = getListData