如何使用Node.js爬取任意网页资源并输出PDF文件到本地


Posted in Javascript onJune 17, 2019

需求:

  • 使用Node.js爬取网页资源,开箱即用的配置
  • 将爬取到的网页内容以PDF格式输出

如果你是一名技术人员,那么可以看我接下来的文章,否则,请直接移步到我的github仓库,直接看文档使用即可

仓库地址:附带文档和源码

本需求使用到的技术:Node.js和puppeteer

  • puppeteer 官网地址: puppeteer地址
  • Node.js官网地址:链接描述
  • Puppeteer是谷歌官方出品的一个通过DevTools协议控制headless Chrome的Node库。可以通过Puppeteer的提供的api直接控制Chrome模拟大部分用户操作来进行UI Test或者作为爬虫访问页面来收集数据。
  • 环境和安装
  • Puppeteer本身依赖6.4以上的Node,但是为了异步超级好用的async/await,推荐使用7.6版本以上的Node。另外headless Chrome本身对服务器依赖的库的版本要求比较高,centos服务器依赖偏稳定,v6很难使用headless Chrome,提升依赖版本可能出现各种服务器问题(包括且不限于无法使用ssh),最好使用高版本服务器。(建议使用最新版本的Node.js)

小试牛刀,爬取京东资源

const puppeteer = require('puppeteer'); // 引入依赖 
(async () => { //使用async函数完美异步 
const browser = await puppeteer.launch(); //打开新的浏览器
const page = await browser.newPage(); // 打开新的网页 
await page.goto('https://www.jd.com/'); //前往里面 'url' 的网页
const result = await page.evaluate(() => { //这个result数组包含所有的图片src地址
let arr = []; //这个箭头函数内部写处理的逻辑 
const imgs = document.querySelectorAll('img');
imgs.forEach(function (item) {
arr.push(item.src)
})
return arr 
});
// '此时的result就是得到的爬虫数据,可以通过'fs'模块保存'
})()

复制过去 使用命令行命令 ` node 文件名 ` 就可以运行获取爬虫数据了 这个 puppeteer 的包 ,其实是替我们开启了另一个浏览器,重新去开启网页,获取它们的数据。

  • 上面只爬取了京东首页的图片内容,假设我的需求进一步扩大,需要爬取京东首页中的所有<a> 标签对应的跳转网页中的所有 title的文字内容,最后放到一个数组中。
  • 我们的async函数上面一共分了五步, 只有 puppeteer.launch() ,browser.newPage(), browser.close() 是固定的写法。
  • page.goto 指定我们去哪个网页爬取数据,可以更换内部url地址,也可以多次调用这个方法。
  • page.evaluate 这个函数,内部是处理我们进入想要爬取网页的数据逻辑
  • page.goto和page.evaluate两个方法,可以在async内部调用多次,那意味着我们可以先进入京东网页,处理逻辑后,再次调用page.goto这个函数

注意,上面这一切逻辑,都是puppeteer这个包帮我们在看不见的地方开启了另外一个浏览器,然后处理逻辑,所以最终要调用browser.close()方法关闭那个浏览器。

这时候我们对上一篇的代码进行优化,爬取对应的资源。

const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://www.jd.com/');
const hrefArr = await page.evaluate(() => {
let arr = [];
const aNodes = document.querySelectorAll('.cate_menu_lk');
aNodes.forEach(function (item) {
arr.push(item.href)
})
return arr
});
let arr = [];
for (let i = 0; i < hrefArr.length; i++) {
const url = hrefArr[i];
console.log(url) //这里可以打印 
await page.goto(url);
const result = await page.evaluate(() => { //这个方法内部console.log无效 
return $('title').text(); //返回每个界面的title文字内容
});
arr.push(result) //每次循环给数组中添加对应的值
}
console.log(arr) //得到对应的数据 可以通过Node.js的 fs 模块保存到本地
await browser.close()
})()

上面有天坑 page.evaluate函数内部的console.log不能打印,而且内部不能获取外部的变量,只能return返回,
使用的选择器必须先去对应界面的控制台实验过能不能选择DOM再使用,比如京东无法使用querySelector。这里由于
京东的分界面都使用了jQuery,所以我们可以用jQuery,总之他们开发能用的选择器,我们都可以用,否则就不可以。

接下来我们直接来爬取Node.js的官网首页然后直接生成PDF

无论您是否了解Node.js和puppeteer的爬虫的人员都可以操作,请您一定万分仔细阅读本文档并按顺序执行每一步

本项目实现需求:给我们一个网页地址,爬取他的网页内容,然后输出成我们想要的PDF格式文档,请注意,是高质量的PDF文档

  • 第一步,安装Node.js ,推荐http://nodejs.cn/download/,Node.js的中文官网下载对应的操作系统包
  • 第二步,在下载安装完了Node.js后, 启动windows命令行工具(windows下启动系统搜索功能,输入cmd,回车,就出来了)
  • 第三步 需要查看环境变量是否已经自动配置,在命令行工具中输入 node -v,如果出现 v10. ***字段,则说明成功安装Node.js
  • 第四步 如果您在第三步发现输入node -v还是没有出现 对应的字段,那么请您重启电脑即可
  • 第五步 打开本项目文件夹,打开命令行工具(windows系统中直接在文件的url地址栏输入cmd就可以打开了),输入 npm i cnpm nodemon -g
  • 第六步 下载puppeteer爬虫包,在完成第五步后,使用cnpm i puppeteer --save 命令 即可下载
  • 第七步 完成第六步下载后,打开本项目的url.js,将您需要爬虫爬取的网页地址替换上去(默认是http://nodejs.cn/)
  • 第八步 在命令行中输入 nodemon index.js 即可爬取对应的内容,并且自动输出到当前文件夹下面的index.pdf文件中

TIPS: 本项目设计思想就是一个网页一个PDF文件,所以每次爬取一个单独页面后,请把index.pdf拷贝出去,然后继续更换url地址,继续爬取,生成新的PDF文件,当然,您也可以通过循环编译等方式去一次性爬取多个网页生成多个PDF文件。

对应像京东首页这样的开启了图片懒加载的网页,爬取到的部分内容是loading状态的内容,对于有一些反爬虫机制的网页,爬虫也会出现问题,但是绝大多数网站都是可以的

const puppeteer = require('puppeteer');
const url = require('./url');
(async () => {
const browser = await puppeteer.launch({ headless: true })
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
});
await browser.close()
})()

文件解构设计

如何使用Node.js爬取任意网页资源并输出PDF文件到本地

数据在这个时代非常珍贵,按照网页的设计逻辑,选定特定的href的地址,可以先直接获取对应的资源,也可以通过再次使用 page.goto方法进入,再调用 page.evaluate() 处理逻辑,或者输出对应的PDF文件,当然也可以一口气输出多个PDF文件~

这里就不做过多介绍了,毕竟 Node.js 是可以上天的,或许未来它真的什么都能做。这么优质简短的教程,请收藏
或者转发给您的朋友,谢谢。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
判断是否输入完毕再激活提交按钮
Jun 26 Javascript
JS在IE和FireFox之间常用函数的区别小结
Mar 12 Javascript
JS的反射问题
Apr 07 Javascript
js计算两个时间之间天数差的实例代码
Nov 19 Javascript
Iframe 自动适应页面的高度示例代码
Feb 26 Javascript
angularjs实现与服务器交互分享
Jun 24 Javascript
JavaScript判断表单为空及获取焦点的方法
Feb 12 Javascript
Ionic如何创建APP项目
Jun 03 Javascript
微信小程序 网络API 上传、下载详解
Nov 09 Javascript
解决JQuery的ajax函数执行失败alert函数弹框一闪而过问题
Apr 10 jQuery
vue切换菜单取消未完成接口请求的案例
Nov 13 Javascript
JS算法教程之字符串去重与字符串反转
Dec 15 Javascript
javascript使用substring实现的展开与收缩文字功能示例
Jun 17 #Javascript
vue+element加入签名效果(移动端可用)
Jun 17 #Javascript
详解Vue.js中引入图片路径的几种方式
Jun 17 #Javascript
最简单的vue消息提示全局组件的方法
Jun 16 #Javascript
如何进行微信公众号开发的本地调试的方法
Jun 16 #Javascript
详解vue微信网页授权最终解决方案
Jun 16 #Javascript
浅谈一种让小程序支持JSX语法的新思路
Jun 16 #Javascript
You might like
通过JavaScript或PHP检测Android设备的代码
2011/03/09 PHP
php实现基于PDO的预处理示例
2017/03/28 PHP
php 获取xml接口数据的处理方法
2018/05/31 PHP
JavaScript 常用函数
2009/12/30 Javascript
JavaScript 判断指定字符串是否为有效数字
2010/05/11 Javascript
jQuery写的日历(包括日历的样式及功能)
2013/04/23 Javascript
javascript解决innerText浏览器兼容问题思路代码
2013/05/17 Javascript
jquery实现网页查找功能示例分享
2014/02/12 Javascript
js 模式窗口(模式对话框和非模式对话框)的使用介绍
2014/07/17 Javascript
javascript实现浏览器窗口传递参数的方法
2014/09/03 Javascript
javascript+HTML5的Canvas实现Lab单车动画效果
2015/08/07 Javascript
js中json处理总结之JSON.parse
2016/10/14 Javascript
基于Layer+jQuery的自定义弹框
2020/05/26 Javascript
JavaScript中${pageContext.request.contextPath}取值问题及解决方案
2016/12/08 Javascript
js原生方法被覆盖,从新赋值原生的方法
2018/01/02 Javascript
vuex进阶知识点巩固
2018/05/20 Javascript
js中怎么判断两个字符串相等的实例
2019/01/17 Javascript
浅谈vuex为什么不建议在action中修改state
2020/02/02 Javascript
javascript如何使用函数random来实现课堂随机点名方法详解
2020/07/28 Javascript
解决python测试opencv时imread导致的错误问题
2019/01/26 Python
python实现整数的二进制循环移位
2019/03/08 Python
python如何保存文本文件
2020/06/07 Python
python 输入字符串生成所有有效的IP地址(LeetCode 93号题)
2020/10/15 Python
css 元素选择器的简单实例
2016/05/23 HTML / CSS
HTML5的革新 结构之美
2011/06/20 HTML / CSS
雅诗兰黛美国官网:Estee Lauder美国
2016/07/21 全球购物
外贸主管求职简历的自我评价
2013/10/23 职场文书
房地产销售员的自我评价分享
2013/12/04 职场文书
人事档案接收函
2014/01/12 职场文书
报纸媒体创意广告词
2014/03/17 职场文书
书香家庭事迹材料
2014/05/09 职场文书
节能环保家庭事迹材料
2014/08/27 职场文书
夫妻吵架保证书
2015/05/08 职场文书
2015年小学总务工作总结
2015/07/21 职场文书
据Python爬虫不靠谱预测可知今年双十一销售额将超过6000亿元
2021/11/11 Python
SpringBoot 集成短信和邮件 以阿里云短信服务为例
2022/04/22 Java/Android