想要自动从网页抓一些数据或者想把一坨从什么博客上拉来的数据转成一种有结构的数据?

居然没有现成的API可以取数据?!!! !@#$@#$…

没关系 网页抓取可以解决。

什么是网页抓取? 你可能会问。。。

网页抓取是以编程的方式(通常不用浏览器参与)检索网页的内容并从中提取数据的过程。

 

本文,小编会给大家展示一套强大的抓取工具,可以快速的对网面进行抓取,而且容易上手,它是由javascript 和node.js实现的。

 

最近我需要爬一些大数量(谦虚的说)的页面,然后分析它们从中找到一些规律。 你知道,实在太长时间没有干过种事了。。。这么说吧, 手头基本上是没有现成的工具可以用了。。

 

我必须承认我实在太喜欢node.js了。 Node.js是一个用来脱离浏览器写javascript程序的框架。 在Atwood’s 定律的指引下, node.js有了一套很强大的工具来帮助大家开发网络程序。你不光可以用node.js来开发webserver/websocket的代码, 我发现它还可以满足我一些日常的脚本需要。 所以我开始寻找node.js在网页抓取方面的现成库或工具, 果然,我找到了 Cheerio. Cheerio 是一个Node.js的库, 它可以从一坨html的片断中构建DOM结构,然后提供像jquery一样的css选择器查询。

 

太好了! 因为,在这个世界上CSS和CSS驱动的样式链表几乎是唯一的网页组织方式。(CSS干的好!)最近人们往往使用CSS class风格的方式来制作各种结构的网页。别误解我,这个并不是解决问题的金钥匙,我依然要处理大量的网页,大部分是杂乱无章的。 但是对我来说 CSS选择器提供一个强大快捷而简单工具,从html中进行有效的的数据识别。 我典型的网页抓取流程是这样的, 首先用firebug或chrome开发者工具分析一下目标网页的结构。主要关注的是我感兴趣的数据即目标数据的css选择器。 接下来就是用node.js搞起了。

 

如果你没有安装node.js或者很久没有升级了, 那么从这里下载。 安装程序不仅会安装node.js本身,还会装一个叫做npm的node 工具包管理器,npm可以用来快速下载并安装node.js的库。 这果我们用npm来安装Cheerio这个库。 运行以下这条命令。

npm install cheerio

 

 

一旦Cheerio安装完成, 我们就可以开始工作了。 首先让我们来看一段javascript代码 这段代码可以下载任意一个网页的内容。

var http = require("http");
 
// Utility function that downloads a URL and invokes
// callback with the data.
function download(url, callback) {
http.get(url, function(res) {
var data = "";
res.on('data', function (chunk) {
data += chunk;
});
res.on("end", function() {
callback(data);
});
}).on("error", function() {
callback(null);
});
}

 

 这段代码可以异步下载任意的URL (通过 HTTP GET方法), 而且在完成下载的时候,它会调用回调函数并把下载的内容当做参数传进去。接下的一段代码可以下载任意一个网页并将其内容输出到控制台。

 

注意: 请大家从源码中引用download.js  只要简单的远行如下代码。

node download.js

 

让我们详细看一下代码。

var url = "http://www.dailymail.co.uk/news/article-2297585/Wild-squirrels-pose-charming-pictures-photographer-hides-nuts-miniature-props.html"
 
download(url, function(data) {
if (data) {
console.log(data);
}
else console.log("error");  
});

 

这段代码会从指定的url下载内容并把内容打印到控制台。 现在我们已经有了可以从网页下载的内容的方法, 接下来就看Cheerio如何去提取我们感兴趣的数据了。

 

在实际操作前,我们还要做一点研究和实验,以帮助我们理解目标网页的布局结构, 这样就可提取出人感兴趣的内容了。 在这个具体的例子里, 我们试图把这些url里的主要的图片取出来。 我们可以先用浏览器打开这些网页,然后找到一个可以定位到这些图片的方法, 你可以用chrome开发者工具 或直接看源码(比较难)可以具体的分离定位这些图片,明白了么? 让我们来看代码吧。

注意:  请引用 squirrel.js 

var cheerio = require("cheerio");
 
var url = "http://www.dailymail.co.uk/news/article-2297585/Wild-squirrels-pose-charming-pictures-photographer-hides-nuts-miniature-props.html"
 
download(url, function(data) {
if (data) {
//console.log(data);
 
var $ = cheerio.load(data);
$("div.artSplitter > img.blkBorder").each(function(i, e) {
console.log($(e).attr("src"));
});
 
console.log("done");
}
else console.log("error");  
});


引入cheerio模块后, 我们可以用之前写好的download方法下载目标网页的内容。 一旦我们有了数据, cheerio.load方法就会把HTML内容解析成DOM对象 并且可以像jquery css选择器查询那样对这个DOM进行筛选,(注意:我把这个变量叫做$这样就更像jquery了)。在目标网页,我注意到这些图片所在的div都有一个叫做 “artSplitter”的class, 而且这些图片本身都有一个叫做”blkBorderf”的class。 为了能将它们唯一的找到,我写了一条css选择器查询语句

$("div.artSplitter > img.blkBorder")


这个语句会返回一个图片对象列表。 然后我们用each方法遍历这些图片然后把每一个图片的src打印出来。效果还不错。。。 我们再来看另外一个例子, 请引用 echo.js 源码。

var cheerio = require("cheerio");
 
var url = "http://www.echojs.com/";
 
download(url, function(data) {
if (data) {
// console.log(data);
var $ = cheerio.load(data);
$("article").each(function(i, e) {
var link = $(e).find("h2>a");
var poster = $(e).find("username").text();
console.log(poster+": ["+link.html()+"]("+link.attr("href")+")");
});
}
});

 

在这个栗子里, 目标是echojs.com。 我想把这个网页上所有文章的链接抓取并以markdown的格式打印出来。 首先我们用以下的语句把所有的artical节点都找到

$("article")

 

然后遍历所有的节点,找到在h2下的a标签 用以下的语句

var link = $(e).find("h2>a");

 

同样,我可以用以下语句找到文章作者的名字

var link = $(e).find("h2>a");


希望你能从这篇关于node.js和chreerio的文章中得到一些快乐吧。 请大家移步 Cheerio documentation 获取列多的信息。

虽然它可能不是适用于所有大型的网页抓取,但它绝对是一个强大的工具, 尤其对于我们前端javascript jquery的开发来说。