居然没有现成的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这个库。 运行以下这条命令。
1
|
npm install cheerio
|
一旦Cheerio安装完成, 我们就可以开始工作了。 首先让我们来看一段javascript代码 这段代码可以下载任意一个网页的内容。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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
只要简单的远行如下代码。
1
|
node download.js
|
让我们详细看一下代码。
1
2
3
4
5
6
7
8
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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选择器查询语句
1
|
$(
"div.artSplitter > img.blkBorder"
)
|
这个语句会返回一个图片对象列表。 然后我们用each方法遍历这些图片然后把每一个图片的src打印出来。效果还不错。。。 我们再来看另外一个例子, 请引用 echo.js 源码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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节点都找到
1
|
$(
"article"
)
|
然后遍历所有的节点,找到在h2下的a标签 用以下的语句
1
|
var
link = $(e).find(
"h2>a"
);
|
同样,我可以用以下语句找到文章作者的名字
1
|
var
poster = $(e).find(
"username"
).text();
|
希望你能从这篇关于node.js和chreerio的文章中得到一些快乐吧。 请大家移步 Cheerio documentation 获取列多的信息。
虽然它可能不是适用于所有大型的网页抓取,但它绝对是一个强大的工具, 尤其对于我们前端javascript jquery的开发来说。
原文地址:
http://www.storminthecastle.com/2013/08/25/use-node-js-to-extract-data-from-the-web-for-fun-and-profit/