Node.js实现的简易网页抓取功能示例

现今,网页抓取已经是一种人所共知的技术了,然而依然存在着诸多复杂性, 简单的网页爬虫依然难以胜任Ajax轮训、XMLHttpRequest,WebSockets,Flash Sockets等各种复杂技术所开发出来的现代化网站。

我们以我们在Hubdoc这个项目上的基础需求为例,在这个项目中,我们从银行,公共事业和信用卡公司的网站上抓取帐单金额,到期日期,账户号码,以及最重要的:近期账单的pdf。对于这个项目,我一开始采用了很简单的方案(暂时并没有使用我们正在评估的昂贵的商业化产品)——我以前在MessageLab/Symantec使用Perl做过的一个简单的爬虫项目。但是结果很不顺利,垃圾邮件发送者所制作的网站要比银行和公共事业公司的网站简单的多得多。

那么如何解决这个问题呢?我们主要从使用Mikea开发的优秀 request库开始。在浏览器中发出请求,并在Network窗口中查看到底发送出去了什么请求头,然后把这些请求头拷贝到代码里。这个过程很简单。仅仅是跟踪从登陆开始,到下载Pdf文件结束的这个过程,然后模拟这个过程的所有的请求而已。为了使类似的事情处理起来变得容易,并且能让网络开发者们更加合理地写爬虫程序,我把从HTML上取到结果的方把导出到jQuery中(使用轻量级 cheerio库),这使得相似的工作变得简单,也使利用CSS选择子选取一个页面中的元素变得较为简单。整个过程被包装进一个框架,而这个框架也可以做额外的工作,例如从数据库中拾取证书,加载个体机器人,和UI通过socket.io沟通。

对于一些web站点来说这个是有效的,但这仅仅是JS脚本,而不是我那个被这些公司放在他们站点上的node.js的code。他们对遗留下来的问题,针对复杂性就行分层,使得你非常难去弄明白该做什么来得到登录的信息点。对于一些站点我尝试了几天通过与request()库结合来获取,但仍是徒然。

在几近崩溃后,我发现了node-phantomjs,这个库可以让我从node中控制phantomjsheadless webkit浏览器(译者注:这个我没想到一个对应的名词,headless这里的意思是渲染页面在后台完成,无需显示设备)。这看起来是一种简单的解决方案,但是还有一些phantomjs无法回避的问题需要解决:

1.PhantomJS只能告诉你页面是否完成了加载,但是你无法确定这个过程中是否存在通过JavaScript或者meta标签实现的重定向(redirect)。特别是JavaScript使用setTimeout()来延迟调用的时候。

2.PhantomJS为你提供了一个页面加载开始(pageLoadStarted)的钩子,允许你处理上面提到的问题,但是这个机能只能在你确定要加载的页面数,在每个页面加载完成时减少这个数字,并且为可能的超时提供处理(因为这种事情并不总是会发生),这样当你的数字减少为0,就可以调用你的回调函数了。这种方式可以工作,但是总让人觉得有点像是黑客手段。

3.PhantomJS每抓取一个页面需要一个完整独立的进程,因为如果不这样,无法分离每个页面之间的cookies。如果你是用同一个phantomjs进程,已经登录的页面中的session会被发送到另一个页面中。

4.无法使用PhantomJS下载资源 - 你只能将页面保存为png或者pdf。这很有用,但是这意味着我们需要求助于request()来下载pdf。

5.由于上述的原因,我必须找到一个方法来将cookie从PhantomJS的session中分发到request()的session库中去。只需要将document.cookie的字符串分发过去,解析它,然后将其注入到request()的cookie jar中去。

6.将变量注入到浏览器session中并不是件容易的事情。要这么做我需要创建一个字符串来建立一个Javascript函数。

代码如下:

Robot.prototype.add_page_data = function (page, name, data) {
 page.evaluate(
 "function () { var " + name + " = window." + name + " = " + JSON.stringify(data) + "}"
 );
}

7.一些网站总是充斥着console.log()之类的代码,也需要将他们重新定义,输出到我们希望的位置。为了完成这个,我这么做:

代码如下:

if (!console.log) {
    var iframe = document.createElement("iframe");
    document.body.appendChild(iframe);
    console = window.frames[0].console;
}

8.一些网站总是充斥着console.log()之类的代码,也需要将他们重新定义,输出到我们希望的位置。为了完成这个,我这么做:

代码如下:

if (!console.log) {
    var iframe = document.createElement("iframe");
    document.body.appendChild(iframe);
    console = window.frames[0].console;
}

9.告诉浏览器我点击了a标签也是件很不容易的事情,为了完成这些事情,我加入了以下的代码:

代码如下:

var clickElement = window.clickElement = function (id){
    var a = document.getElementById(id);
    var e = document.createEvent("MouseEvents");
    e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    a.dispatchEvent(e);
 };

10.我还需要限制浏览器session的最大并发量,从而保障我们不会爆掉服务器。虽然这么说,可是这个限制要比昂贵的商业解决方案所能提供的高很多。(译者注:即商业解决方案的并发量比这个解决方案大)

所有的工作结束后,我就有一个比较体面的 PhantomJS + request 的爬虫解决方案。必须使用 PhantomJS 登录后才可以返回去 request() 请求,它将使用在 PhantomJS 中设置的 Cookie 来验证登录的会话。这是一个巨大的胜利,因为我们可以使用 request() 的流来下载 pdf文件。

整个的计划就是为了让 Web 开发者相对容易的理解如何使用 jQuery 和 CSS 选择器来创建不同 Web 网站的爬虫,我还没有成功证明这个思路可行,但相信很快会了。

(0)

相关推荐

  • Node.js抓取中文网页乱码问题和解决方法

    Node.js 抓取非 utf-8 的中文网页时会出现乱码问题,比如网易的首页编码是 gb2312,抓取时会出现乱码 复制代码 代码如下: var request = require('request')  var url = 'http://www.163.com' request(url, function (err, res, body) {      console.log(body) }) 可以使用 iconv-lite来解决 安装 复制代码 代码如下: npm install ico

  • 利用NodeJS和PhantomJS抓取网站页面信息以及网站截图

    利用PhantomJS做网页截图经济适用,但其API较少,做其他功能就比较吃力了.例如,其自带的Web Server Mongoose最高只能同时支持10个请求,指望他能独立成为一个服务是不怎么实际的.所以这里需要另一个语言来支撑服务,这里选用NodeJS来完成. 安装PhantomJS 首先,去PhantomJS官网下载对应平台的版本,或者下载源代码自行编译.然后将PhantomJS配置进环境变量,输入 $ phantomjs 如果有反应,那么就可以进行下一步了. 利用PhantomJS进行简

  • node.js抓取并分析网页内容有无特殊内容的js文件

    nodejs获取网页内容绑定data事件,获取到的数据会分几次相应,如果想全局内容匹配,需要等待请求结束,在end结束事件里把累积起来的全局数据进行操作! 举个例子,比如要在页面中找有没有www.baidu.com,不多说了,直接放代码: //引入模块 var http = require("http"), fs = require('fs'), url = require('url'); //写入文件,把结果写入不同的文件 var writeRes = function(p, r)

  • 使用phantomjs进行网页抓取的实现代码

    phantomjs因为是无头浏览器可以跑js,所以同样可以跑dom节点,用来进行网页抓取是再好不过了. 比如我们要批量抓取网页 "历史上的今天" 的内容.网站 对dom结构的观察发现,我们只需要取到 .list li a的title值即可.因此我们利用高级选择器构建dom片段 var d= '' var c = document.querySelectorAll('.list li a') var l = c.length; for(var i =0;i<l;i++){ d=d+

  • Node.JS利用PhantomJs抓取网页入门教程

    前言 当想用 nodejs 抓取一些网页 , 我第一反应想到的就是使用 http 模块 , 比如抓取百度首页: var http = require('http'); var req = http.request('http://www.baidu.com/', function (res) { res.setEncoding('utf8'); res.on('data', function (chunk) { //响应内容 console.log(chunk) }); }); req.end(

  • nodejs通过phantomjs实现下载网页

    功能其实很见简单,通过 phantomjs.exe 采集 url 加载的资源,通过子进程的方式,启动nodejs 加载所有的资源,对于css的资源,匹配css内容,下载里面的url资源 当然功能还是很简单的,在响应式设计和异步加载的情况下,还是有很多资源没有能够下载,需要根据实际情况处理下 首先当然是下载 nodejs 和 phantomjs 下面是 phantomjs.exe 执行的 down.js var page = require('webpage').create(), system

  • Node.js实现的简易网页抓取功能示例

    现今,网页抓取已经是一种人所共知的技术了,然而依然存在着诸多复杂性, 简单的网页爬虫依然难以胜任Ajax轮训.XMLHttpRequest,WebSockets,Flash Sockets等各种复杂技术所开发出来的现代化网站. 我们以我们在Hubdoc这个项目上的基础需求为例,在这个项目中,我们从银行,公共事业和信用卡公司的网站上抓取帐单金额,到期日期,账户号码,以及最重要的:近期账单的pdf.对于这个项目,我一开始采用了很简单的方案(暂时并没有使用我们正在评估的昂贵的商业化产品)--我以前在M

  • Python爬虫实现网页信息抓取功能示例【URL与正则模块】

    本文实例讲述了Python爬虫实现网页信息抓取功能.分享给大家供大家参考,具体如下: 首先实现关于网页解析.读取等操作我们要用到以下几个模块 import urllib import urllib2 import re 我们可以尝试一下用readline方法读某个网站,比如说百度 def test(): f=urllib.urlopen('http://www.baidu.com') while True: firstLine=f.readline() print firstLine 下面我们说

  • PHP通过CURL实现定时任务的图片抓取功能示例

    本文实例讲述了PHP通过CURL实现定时任务的图片抓取功能.分享给大家供大家参考,具体如下: 下文为各位介绍一个PHP定时任务通过CURL图片的抓取例子,希望例子对大家帮助,基本思路就是通过一个URL连接,将所有图片的地址抓取下来,然后循环打开图片,利用文件操作函数下载下来,保存到本地,并且把图片的alt属性也抓取下来,最后将数据保存到自己数据库. 废话不多说,看程序就能明白了,其中,需要用到PHP定时任务和PHP的一个第三方插件simple_html_dom.php 的使用,参考simple_

  • Python简单实现网页内容抓取功能示例

    本文实例讲述了Python简单实现网页内容抓取功能.分享给大家供大家参考,具体如下: 使用模块: import urllib2 import urllib 普通抓取实例: #!/usr/bin/python # -*- coding: UTF-8 -*- import urllib2 url = 'http://www.baidu.com' #创建request对象 request = urllib2.Request(url) #发送请求,获取结果 try: response = urllib2

  • 用Node.js通过sitemap.xml批量抓取美女图片

    之前看了很多个版本,自己也搞一个. 1. 支持指定保存到哪个目录 2. 按文章进行分目录存放 3. 支持设置并行下载上限 下次有空再搞个整站下载的. package.json { "name": "me2sex-images", "version": "0.0.1", "description": "Batch download images from http://me2-sex.lofter.

  • 如何利用Node.js做简单的图片爬取

    目录 介绍 安装引入 创建实例 元素捕获 下载图片 结语 介绍 爬虫的主要目的是收集互联网上公开的一些特定数据.利用这些数据我们可以能进行分析一些趋势对比,或者训练模型做深度学习等等.本期我们就将介绍一个专门用于网络抓取的 node.js 包—— node-crawler ,并且我们将用它完成一个简单的爬虫案例来爬取网页上图片并下载到本地. node-crawler 是一个轻量级的 node.js 爬虫工具,兼顾了高效与便利性,支持分布式爬虫系统,支持硬编码,支持http前级代理.而且,它完全是

  • java简单网页抓取的实现方法

    本文实例讲述了java简单网页抓取的实现方法.分享给大家供大家参考.具体分析如下: 背景介绍 一 tcp简介 1 tcp 实现网络中点对点的传输 2 传输是通过ports和sockets ports提供了不同类型的传输(例如 http的port是80) 1)sockets可以绑定在特定端口上,并且提供传输功能 2)一个port可以连接多个socket 二 URL简介 URL 是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址. 互联网上的每个文件都有一个唯一的

  • C#基于正则表达式实现获取网页中所有信息的网页抓取类实例

    本文实例讲述了C#基于正则表达式实现获取网页中所有信息的网页抓取类.分享给大家供大家参考,具体如下: 类的代码: using System; using System.Data; using System.Configuration; using System.Net; using System.IO; using System.Text; using System.Collections.Generic; using System.Text.RegularExpressions; using

  • Linux使用Node.js建立访问静态网页的服务实例详解

    Linux使用Node.js建立访问静态网页的服务实例详解 一.安装node.js运行所需要的环境,:http://www.jb51.net/article/79536.htm 二.创建node目录(/node/www),并在目录下创建node.js服务文件server.js var http = require('http'); var fs = require('fs');//引入文件读取模块 var documentRoot = '/node/www';//需要访问的文件的存放目录 var

随机推荐