本篇文章针对大家熟知的技术站点作为目标进行技术实践。

确定需求

  访问目标网站并按照筛选条件(关键词、日期、作者)进行检索并获取返回数据中的目标数据。进行技术拆分如下:

  1. 打开目标网站
  2. 找到输入框元素输入关键词,找到日期元素设置日期,找到搜索按钮触发搜索动作
  3. 解析搜索返回的html元素构造目标数据
  4. 将目标数据保存

编写代码

'use strict';
const puppeteer = require('puppeteer');
const csv = require('fast-csv');
const fs = require('fs'); (async () => {
const startUrl = 'https://www.infoq.cn/';
const keyWord = 'CQRS';
const browser = await puppeteer.launch({
slowMo: 100, // 放慢速度
headless: false, // 是否有头
defaultViewport: {// 界面设置
width: 1820,
height: 1080,
},
ignoreHTTPSErrors: false, // 忽略 https 报错
args: ['--start-maximized', '--no-sandbox', '--disable-setuid-sandbox'],
}); const page = await browser.newPage();
await page.goto(startUrl).catch(error => console.log(error));
await page.waitFor(1 * 1000);
await page.click('.search,.iconfont');
await page.type('.search-input', keyWord, { delay: 100 });
const newPagePromise = new Promise(x => browser.once('targetcreated', target => x(target.page())));
await page.click('.search,.iconfont');
const targetPage = await newPagePromise;
const dataCount = await targetPage.$eval('.search-body-main-tips span', el => el && el.innerHTML).catch(error => console.error(error));
if (dataCount && dataCount > 0) {
const dataEle = await targetPage.$$('.search-item');
console.log(dataEle.length);
const stream = fs.createWriteStream('infoq.csv');
const csvStream = csv.format({ headers: true });
csvStream.pipe(stream).on('end', process.exit);
for (let index = 0; index < dataEle.length; index++) {
const element = dataEle[index];
const title = await element.$eval('a', el => el && el.innerHTML).catch(error => console.error(error))
const desc = await element.$eval('.desc', el => el && el.innerHTML).catch(error => console.error(error))
csvStream.write({
标题: title || '',
摘要: desc || '',
});
}
csvStream.end(() => { console.log('写入完毕'); });
}
await targetPage.screenshot({ path: 'infoq.png' });
await browser.close();
})();

具体的如下

总结

  上面的例子还是比较简单的,站点本身是资讯站(其实有搜索接口根本不需要解析html),例子是一个简单的爬虫流程,方便了解puppeteer的能力,下面我也总结一下工作中和自己项目的实际情况。

  1. 上述例子还不能算是一个完整的应用,根据主要业务分析实际应用大概是这个样子: 爬虫的主要业务变化部分有目标站点、筛选条件、站点操作、数据解析、数据落地,这些都可以通过代码搞定,也就是代码是变化的,所以一个可用的爬虫的应用是代码是可动态调整的,根据上面的动态点将一个爬虫业务抽象成一个Task,
  • 它要具备一个参数输入界面(动态输入目标站点、筛选条件等脚本所需参数),每个task的业务不一样,脚本参数不一样,就需要一个动态表单可配置脚本所需参数(Ant design搞一个也够用了);
  • 站点操作会根据实际情况而希望能够动态调整脚本代码,那就引入一个在线的vscode编辑器(实际开发中通常都是测试好的脚本才会写进去,这个地方引入有些牵强,主要是线上发现一些小bug需要快速解决);
  • 数据解析完了后需要落地,这包括保存到本地、推到api接口、或是下载文件成功推送标识等皆可动态参数和脚本实现;
  1. Task主要流程还有一个重要的点就是触发需要一个定时任务方便用户设置各种周期性的需求,不管是考虑用户需求还是躲避爬虫频率限制都很有必要。
  2. Task主要流程完成后还有很重要的基础设施:
  • 应用快速部署,当然要用到docker了。因为puppeteer其实是依赖了Chromium的能力,所以你需要在容器里部署一套可运行的chromium,这里面牵扯到字体、环境问题等麻烦事情,这里我推荐一个使用的镜像browserless/chrome,这个镜像大家可以根据自己需求定制,视频中的界面演示即FullHead,容器环境往往不是完整的操作系统(应该没人用完整的windows环境吧)而是尽量小的linux版本(我本人使用的是egg引入puppeteer),那么就不可能有界面,即无法实现FullHead,FullHead可以帮我们规避一些站点(部分站点检测手段比较强)的反爬手段,这里使用的是xvfb实现了FullHead。
  • 网络检测,无论是切换容器网络还是在应用中使用ip代理我都没搞过就不说了。分布式爬虫我目前没实现所以这里就不说了。
  1. 实际使用中遇到的一些问题,资讯站渲染的比较随意,解析比较复杂,有些数据只是展示而无固定标签或规律展示,puppeteer的元素选择器有css和xpath,但是这个和大家平常用jquery不太一样,最好去看看标准,它的xpath解析就不完整(比如string(.),因为puppeteer要包返回装类型所以就完蛋了,我提了issue,答复目前也只能遍历了,或者有谁知道可以提醒我下)。网络问题,访问时渲染有时候会超时这个要自己根据需求搞了。

大致就到这吧。

Puppeteer爬虫实战(三)的更多相关文章

  1. Python爬虫实战三之实现山东大学无线网络掉线自动重连

    综述 最近山大软件园校区QLSC_STU无线网掉线掉的厉害,连上之后平均十分钟左右掉线一次,很是让人心烦,还能不能愉快地上自习了?能忍吗?反正我是不能忍了,嗯,自己动手,丰衣足食!写个程序解决掉它! ...

  2. Puppeteer爬虫实战(一)

    Puppeteer 爬虫技术实践 信息简介 Puppeteer是Chrome开发团队发布的一个通过Chrome DevTool Protocol来控制浏览器Chrome(下文若无显式称呼Chromiu ...

  3. Python爬虫实战三之爬取嗅事百科段子

    一.前言 俗话说,上班时间是公司的,下班了时间才是自己的.搞点事情,写个爬虫程序,每天定期爬取点段子,看着自己爬的段子,也是一种乐趣. 二.Python爬取嗅事百科段子 1.确定爬取的目标网页 首先我 ...

  4. Python网络爬虫实战(三)照片定位与B站弹幕

    之前两篇已经说完了如何爬取网页以及如何解析其中的数据,那么今天我们就可以开始第一次实战了. 这篇实战包含两个内容. * 利用爬虫调用Api来解析照片的拍摄位置 * 利用爬虫爬取Bilibili视频中的 ...

  5. 爬虫实战(三) 用Python爬取拉勾网

    目录 0.前言 1.初始化 2.爬取数据 3.保存数据 4.数据可视化 5.大功告成 0.前言 最近,博主面临着选方向的困难(唉,选择困难症患者 >﹏<),所以希望了解一下目前不同岗位的就 ...

  6. 自学Python十 爬虫实战三(美女福利续)

    我又来送福利啦!!!不同于上篇文章,这次我们的爬虫采用了多线程,一直以来被所谓的分布式  多线程  爬虫 给唬的怕怕的.今天就来一发多线程爬虫吧,还能看妹子图,想想就觉得很激动!!! 依然是流程解释: ...

  7. Puppeteer爬虫实战(二)

    连接浏览器 上一篇说到了Puppeteer本质是使用了Chrome Devtools协议控制浏览器,本篇就说说连接方式. 常规Hook浏览器 此方式其实就是需要一个浏览器可执行文件(不同平台需要下载对 ...

  8. python网络爬虫实战PDF高清完整版免费下载|百度云盘|Python基础教程免费电子书

    点击获取提取码:vg1y python网络爬虫实战帮助读者学习Python并开发出符合自己要求的网络爬虫.网络爬虫,又被称为网页蜘蛛,网络机器人,是一种按照一定的规则,自动地抓取互联网信息的程序或者脚 ...

  9. 第三百三十节,web爬虫讲解2—urllib库爬虫—实战爬取搜狗微信公众号—抓包软件安装Fiddler4讲解

    第三百三十节,web爬虫讲解2—urllib库爬虫—实战爬取搜狗微信公众号—抓包软件安装Fiddler4讲解 封装模块 #!/usr/bin/env python # -*- coding: utf- ...

随机推荐

  1. FIS3安装与编译

    安装 FIS3 npm install -g fis3 -g 安装到全局目录,必须使用全局安装,当全局安装后才能在命令行(cmd或者终端)找到 fis3 命令 安装过程中遇到问题具体请参考 fis#5 ...

  2. NodeJs通过HTTP模块发起GET|POST请求

    [本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究.若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!] Node.js ...

  3. django 报错处理汇总

    运行 manage.py task时 ,makemigrations抛出以下错误, django.db.utils.OperationalError: (1045, "Access deni ...

  4. 四层发现-UDP发现

    udp发现要注意选择一个不常用的端口,如果目标ip在up时目标端口是开放状态,那么不管目标ip是否为up状态,都不会收到任何回应,只有在目标ip为down状态且目标端口为关闭状态,才会返回一个目标不可 ...

  5. 【Spring】@Transactional 闲聊

    菜瓜:上次的AOP理论知识看完收获挺多的,虽然有一个自定义注解的demo,但还是觉得差点东西 水稻:我也觉得没有跟一遍源码还是差点意思,这次结合@Transactional注解深入源码看一下 菜瓜:事 ...

  6. ES6 promise用法总结

    一   什么时候promise? promise是异步编程的一个解决方案,是一个构造函数,身上带着all,resolve,reject,原型上有cath,then等方法 promise有两个特点: 1 ...

  7. 什么是EL表达式?

    1.什么是EL表达式? EL(Expression Language) 是为了使JSP写起来更加简单.表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简 ...

  8. 深入理解React:diff 算法

    目录 序言 React 的核心思想 传统 diff 算法 React diff 两个假设 三个策略 diff 具体优化 tree diff component diff element diff 小结 ...

  9. css3条件判断_@supports的用法/Window.CSS.supports()的使用

    为了判断浏览器是否支持css3的一些新属性样式,当不兼容该样式的时候,我们可以更优雅的降级处理.这就需要使用到css3的条件判断功能:在css中支持@supports标记.或者在js中使用CSS.su ...

  10. HDU 2236 无题Ⅱ

    HDU 2236 无题Ⅱ 题目大意 这是一个简单的游戏,在一个\(n*n\)的矩阵中,找n个数使得这n个数都在不同的行和列里并且要求这n个数中的最大值和最小值的差值最小. solution 暴枚\(i ...