puppeteer爬虫

8次阅读

共计 2717 个字符,预计需要花费 7 分钟才能阅读完成。

利用空闲时间,学习了下 puppeteer 爬虫,我也想爬取下网上的资源

1. 部分 api

  • puppeteer.launch(options)
参数名称 参数类型 参数说明
ignoreHTTPSErrors boolean 在请求的过程中是否忽略 Https 报错信息,默认为 false
headless boolean 是否以“无头”的模式运行 chrome,也就是不显示 UI,默认为 true
executablePath string 可执行文件的路径,Puppeteer 默认是使用它自带的 chrome webdriver, 如果你想指定一个自己的 webdriver 路径,可以通过这个参数设置
slowMo number 使 Puppeteer 操作减速,单位是毫秒。如果你想看看 Puppeteer 的整个工作过程,这个参数将非常有用
args Array(String) 传递给 chrome 实例的其他参数,比如你可以设置浏览器窗口大小具体参数
timeout number 等待 chrome 实例启动的最长时间,默认是 3000ms,如果传入 0,则不限制时间
dumpio boolean 是否将浏览器锦程 stdout 和 stderr 导入到 process.stdout 和 process.stderr 中,默认为 false
userDataDir string 设置用户数据目录,默认 linux 是在~/.config 目录,window 默认在 C:Users{USER}AppDataLocalGoogleChromeUser Data, 其中 {USER} 代表当前登录的用户名
env Object 指定对 chromium 可见的环境变量,默认为 process.env
devtools boolean 是否为每个选项卡自动打开 DevTools 面板,这个选项只有当 headless 设置为 false 的时候有效
  • browser 对象 api
方法名 说明
browser.close() 返回一个 promise 对象,用于关闭浏览器
browser.newPage() 返回一个 promise 对象,创建一个 page 实例
  • page 对象
方法名 说明
page.goto(url[, options]) 返回一个 promise 对象,url 是目标链接
page.waitForSelector() 等待某个选择器的元素加载之后,这个元素可以是异步加载的
page.evaluate(pageFunction[,args]) 返回一个可序列化的普通对象,pageFunction 表示要在页面执行的函数,args 表示传入给 pageFunction 的参数

2. 爬取电影网站

const puppeteer = require('puppeteer');

/* 爬虫的目标链接地址: 豆瓣电影 */
const url = `https://movie.douban.com/tag/#/?sort=R&range=0,10&tags=`;

const sleep = time => new Promise(resolve => {setTimeout(resolve, time);
});

(async () => {console.log('crawler start to visit the target address');

  /* dumpio 是否将浏览器进程 stdout 和 stderr 导入到 process.stdout 和 process.stderr 中 */
  const browser = await puppeteer.launch({args: ['--no-sandbox'],
    dumpio: false
  });
  const page = await browser.newPage();
  await page.goto(url, {waitUntil: 'networkidle2'});

  await sleep(3000);

  await page.waitForSelector('.more');

  for(let i = 0; i < 1; i++) {await sleep(3000);
    await page.click('.more');
  }

  const result = await page.evaluate(() => {
    let $ = window.$;
    let nodeItems = $('.list-wp a');
    let links = [];
    
    /* 获取对应的元素节点 */
    if(nodeItems.length >= 1) {nodeItems.each((index, item) => {let elem = $(item);
        let movieId = elem.find('div').data('id');
        let title = elem.find('.title').text();
        let rate = Number(elem.find('.rate').text());
        let poster = elem.find('img').attr('src').replace('s_ratio_poster','l_ratio_poster');

        links.push({
          movieId,
          title,
          rate,
          poster,
        })
      })
    }

    return links;
  });

  browser.close();
  console.log(result)
})();

3. 爬取网站内容生成 pdf 文件

const puppeteer = require('puppeteer');
const url = 'https://cn.vuejs.org/v2/guide/';
(async () => {const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto(url, { waitUntil: 'networkidle0'});
    /* 选择你要输出的那个 PDF 文件路径,把爬取到的内容输出到 PDF 中,必须是存在的 PDF,可以是空内容,如果不是空的内容 PDF,那么会覆盖内容 */
    let pdfFilePath = './index.pdf';
    /* 根据你的配置选项,我们这里选择 A4 纸的规格输出 PDF,方便打印 */
    await page.pdf({
        path: pdfFilePath,
        format: 'A4',
        scale: 1,
        printBackground: true,
        landscape: false,
        displayHeaderFooter: false
    });
    browser.close();})()

正在努力学习中,若对你的学习有帮助,留下你的印记呗(点个赞咯 ^_^)

  • 往期好文推荐:

    • 使用 vue 开发移动端管理后台
    • 实现单行及多行文字超出后加省略号
    • node 之本地服务器图片上传
    • 纯 css 实现瀑布流(multi-column 多列及 flex 布局)
正文完
 0

puppeteer爬虫

8次阅读

共计 2650 个字符,预计需要花费 7 分钟才能阅读完成。

@(爬虫)[puppeteer|]
爬虫又称网络机器人。每天或许你都会使用搜索引擎,爬虫便是搜索引擎重要的组成部分,爬取内容做索引。现如今大数据,数据分析很火,那数据哪里来呢,可以通过网络爬虫爬取啊。那我萌就来探讨一下网络爬虫吧。

[TOC]
爬虫的工作原理
如图所示,这是爬虫的流程图,可以看到通过一个种子 URL 开启爬虫的爬取之旅,通过下载网页,解析网页中内容存储,同时解析中网页中的 URL 去除重复后加入到等待爬取的队列。然后从队列中取到下一个等待爬取的 URL 重复以上步骤,是不是很简单呢?
广度(BFS)还是深度(DFS)优先策略
上面也提到在爬取完一个网页后从等待爬取的队列中选取一个 URL 去爬去,那如何选择呢?是选择当前爬取网页中的 URL 还是继续选取当前 URL 中同级 URL 呢?这里的同级 URL 是指来自同一个网页的 URL,这就是爬取策略之分。

广度优先策略(BFS)
广度优先策略便是将当前某个网页中 URL 先爬取完全,再去爬取从当前网页中的 URL 爬取的 URL,这就是 BFS,如果上图的关系图表示网页的关系,那么 BFS 的爬取策略将会是:(A->(B,D,F,G)->(C,F));
深度优先策略(DFS)
深度优先策略爬取某个网页,然后继续去爬取从网页中解析出的 URL,直到爬取完。(A->B->C->D->E->F->G)
下载网页
下载网页看起来很简单,就像在浏览器中输入链接一样,下载完后浏览器便能显示出来。当然结果是并不是这样的简单。
模拟登录
对于一些网页来说需要登录才能看到网页中内容,那爬虫怎么登录呢?其实登录的过程就是获取访问的凭证(cookie,token…)
let cookie = ”;
let j = request.jar()
async function login() {
if (cookie) {
return await Promise.resolve(cookie);
}
return await new Promise((resolve, reject) => {
request.post({
url: ‘url’,
form: {
m: ‘username’,
p: ‘password’,
},
jar: j
}, function(err, res, body) {
if (err) {
reject(err);
return;
}
cookie = j.getCookieString(‘url’);
resolve(cookie);
})
})
}
这里是个简单的栗子,登录获取 cookie, 然后每次请求都带上 cookie.
获取网页内容
有的网页内容是服务端渲染的,没有 CGI 能够获得数据,只能从 html 中解析内容,但是有的网站的内容并不是简单的便能获取内容,像 linkedin 这样的网站并不是简单的能够获得网页内容,网页需要通过浏览器执行后才能获得最终的 html 结构,那怎么解决呢?前面我萌提到浏览器执行,那么我萌有没有可编程的浏览器呢?puppeteer, 谷歌 chrome 团队开源的无头浏览器项目,利用无头浏览器便能模拟用户访问,便能获取最重网页的内容,抓取内容。利用 puppeteer 模拟登录
async function login(username, password) {
const browser = await puppeteer.launch();
page = await browser.newPage();
await page.setViewport({
width: 1400,
height: 1000
})
await page.goto(‘https://maimai.cn/login’);
console.log(page.url())
await page.focus(‘input[type=text]’);
await page.type(username, { delay: 100});
await page.focus(‘input[type=password]’);
await page.type(password, { delay: 100});
await page.$eval(“input[type=submit]”, el => el.click());
await page.waitForNavigation();
return page;
}
执行 login() 后便能像在浏览器中登录后,便能像浏览器中登录后便能获取 html 中的内容,当让 w 哦萌也可以直接请求 CGI
async function crawlData(index, data) {
let dataUrl = `https://maimai.cn/company/contacts?count=20&page=${index}&query=&dist=0&cid=${cinfo.cid}&company=${cinfo.encodename}&forcomp=1&searchTokens=&highlight=false&school=&me=&webcname=&webcid=&jsononly=1`;
await page.goto(dataUrl);
let res = await page.evaluate((e) => {
return document.body.querySelector(‘pre’).innerHTML;
});
console.log(res)
res = JSON.parse(res);
if (res && res.result == ‘ok’ && res.data.contacts && res.data.contacts.length) {
data = data.concat(res.data.contacts.map((item) => {
let contact = item.contact;
console.log(contact.name)
return {
name: contact.name,
occupation: contact.line4.split(‘,’)[0],
company: contact.company,
title: contact.position
}
}));
return await crawlData(++index, data);
}
return data;
}
像有的网站,拉钩,每次爬取的 cookie 都一样,也能利用无头浏览器取爬取,这样每次就不用每次爬取的时候担心 cookie.
写在最后
当然爬虫不仅仅这些,更多的是对网站进行分析,找到合适的爬虫策略。对后关于 puppeteer, 不仅仅可以用来做爬虫,因为可以编程,无头浏览器,可以用来自动化测试等等。

正文完
 0