nodejs抓取动态网页(爬虫爬取的流程和最终如何展示数据的地址?)
优采云 发布时间: 2022-01-25 10:03nodejs抓取动态网页(爬虫爬取的流程和最终如何展示数据的地址?)
其实很早以前我做过即时理财的销售统计,不过是前端js写的。需要在首页的控制台调试面板中粘贴一段代码来执行,点这里。主要是通过定期爬取异步接口来获取数据。然后,通过一定的排序算法得到最终的数据。但这样做有以下缺点:
0. 代码只能在浏览器窗口下运行,关闭浏览器或电脑无效
0. 只能爬取一个页面的数据,不能整合其他页面的数据
0. 爬取的数据无法存储在本地
0. 上面的异步接口数据会被部分过滤,导致我们的重载算法失败
由于最近学习了节点爬虫,所以可以在后台模拟请求,爬取页面数据。而且我已经开通了阿里云服务器,可以把代码放到云端运行。这样,1、2、3就可以解决了。4是因为我不知道这个ajax接口每三分钟更新一次,所以我们可以按照这个来安排权重,保证数据不会重复。说到爬虫,大部分人都会想到python。确实,python有Scrapy等成熟的框架,可以实现强大的爬取功能。但是,节点也有自己的优势。凭借其强大的异步特性,可以轻松实现高效的异步并发请求,节省CPU开销。其实节点爬虫比较简单。让'
在线地址
一、爬虫进程
我们的最终目标是爬取利马财经的每日销售额,并了解哪些产品被销售,哪些用户在什么时间购买了每个产品。首先介绍爬取的主要步骤:
1. 结构分析
如果我们要爬取页面的数据,第一步当然是分析页面的结构,要爬哪些页面,页面的结构是什么,是否登录;是否有ajax接口,返回什么样的数据等。
2. 数据抓取
分析好爬取哪些页面和ajax后,就需要爬取数据了。现在网页的数据大致分为同步页面和ajax接口。要获取同步页面数据,我们需要先分析网页的结构。Python取数据一般通过正则表达式匹配来获取需要的数据;node有一个cheerio工具,可以将获取到的页面内容转换成jquery对象,然后可以使用jquery强大的dom API来获取node相关的数据。其实看源码的话,这些API的本质就是正则匹配。Ajax接口数据一般为json格式,处理起来比较简单。
3. 数据存储
采集到数据后,会进行简单的筛选,然后将需要的数据保存下来,供后续分析处理。当然我们可以将数据存储在 MySQL 和 Mongodb 等数据库中。这里,为了方便,我们直接使用文件存储。
4. 数据分析
因为我们最终要展示数据,所以需要对原创数据按照一定的维度进行处理和分析,然后返回给客户端。这个过程可以在存储的时候进行处理,也可以在显示的时候,前端发送请求,后台取回存储的数据进行处理。这取决于我们希望如何显示数据。
5. 结果显示
做了这么多工作,一点显示输出都没有,怎么舍得?这又回到了我们的老业务,前端展示页面大家应该都很熟悉了。数据展示更加直观,方便我们进行统计分析。
二、爬虫常用库介绍1. Superagent
Superagent 是一个轻量级的 http 库。是nodejs中一个非常方便的客户端请求代理模块。当我们需要进行get、post、head等网络请求的时候,试试吧。
2. 谢里奥
Cheerio 可以理解为 jquery 的 Node.js 版本,用于从带有 css 选择器的网页中获取数据,方式与 jquery 完全相同。
3. 异步
Async 是一个流程控制工具包,提供了直接且强大的异步函数 mapLimit(arr, limit, iterator, callback)。我们主要使用这种方法。您可以在官方网站上查看API。
4. arr-del
arr-del 是我自己写的一个删除数组元素方法的工具。可以通过传入一个由要删除的数组元素的索引组成的数组来执行一次性删除。
5. arr-排序
arr-sort 是我自己编写的用于对数组进行排序的工具。可以按一个或多个属性排序,支持嵌套属性。并且可以指定每个条件下的排序方向,并支持传入比较函数。
三、页面结构分析
让我们重复我们首先抓取的想法。利马理财在线的产品主要是普通的利马银行(光大银行最新的理财产品,手续复杂,前期投入大,基本没人买,这里不计)。定期我们可以爬取财务页面的ajax接口:. (更新:近期定期缺货,可能看不到数据)数据如下图所示:
这包括在线销售的所有常规产品。ajax数据只有产品本身相关的信息,比如产品id、募集金额、当前销售额、年化收益率、投资天数等,并没有哪些用户购买了产品的信息。. 所以我们需要到它的商品详情页面去爬取id参数,比如Lima Jucai-December issue HLB01239511。详情页有一栏投资记录,里面收录了我们需要的信息,如下图所示:
但是详情页需要我们登录才能查看,这就需要我们带着cookie来访问,而且cookie的有效期是有限的。如何让我们的cookie保持登录状态?请看下文。
其实Lima Vault也有类似的ajax接口:,但是里面的相关数据都写死了,没有意义。而且,金库的详情页没有投资记录信息。这就需要我们爬取开头提到的首页的ajax接口:. 但是后来发*敏*感*词*库统计数据会立即低于真实数据。
四、爬虫代码分析1.获取登录cookie
因为商品详情页面需要登录,所以我们需要先获取登录cookie。getCookie 方法如下:
function getCookie() {
superagent.post('https://www.lmlc.com/user/s/web/logon')
.type('form')
.send({
phone: phone,
password: password,
productCode: "LMLC",
origin: "PC"
})
.end(function(err, res) {
if (err) {
handleErr(err.message);
return;
}
cookie = res.header['set-cookie']; //从response中得到cookie
emitter.emit("setCookeie");
})
}
手机和密码参数是命令行传入的,就是你用手机号登录的账号和密码。我们使用superagent模拟即时财务管理登录界面的请求:. 传入相应的参数,在回调中我们获取到header的set-cookie信息,并发出setCookieie事件。因为我们设置了*敏*感*词*事件:emitter.on("setCookie", requestData),一旦获取到cookie,我们就会执行requestData方法。
2. 财务页面ajax的爬取
requestData 方法的代码如下:
<p>function requestData() {
superagent.get('https://www.lmlc.com/web/product/product_list?pageSize=100&pageNo=1&type=0')
.end(function(err,pres){
// 常规的错误处理
if (err) {
handleErr(err.message);
return;
}
// 在这里清空数据,避免一个文件被同时写入
if(clearProd){
fs.writeFileSync('data/prod.json', JSON.stringify([]));
clearProd = false;
}
let addData = JSON.parse(pres.text).data;
let formatedAddData = formatData(addData.result);
let pageUrls = [];
if(addData.totalPage > 1){
handleErr('产品个数超过100个!');
return;
}
for(let i=0,len=addData.result.length; i