爬虫平台实现的功能

一般来说,一个完整的爬虫包含五个模块:链接调度、网页下载、数据抽取、链接发现、数据存储。神箭手爬虫平台对这五个模块做了最大程度的支持,以方便开发者迅速开发出想要的爬虫。

链接调度

平台实现了一个完善的分布式链接调度,调度细节是对开发者是透明的,不过开发者可以通过平台设定好的一些规则,来从整体上控制链接调度的顺序。完善的分布式链接调度,使得开发者开发出来的爬虫,直接具有分布式爬虫的能力,可以通过简单的加减节点操作,达到加速或减速爬取速度的目的。

网页下载

平台实现了三种方式的网页下载,高效且常用的HTTP、有渲染功能的HtmlUnitPhantomJS
默认是HTTP的方式下载,可以配置使用其他另外两种。

数据抽取

平台支持三种数据抽取方式,适用于网页的XPath、适用于json数据的JsonPath和适用于所有文本的正则表达式
整个数据的抽取需要开发者在configs中配置,可以结合使用这三种方式进行网页抽取。

链接发现

平台实现了通用的自动链接发现,不过对于定向爬虫,一般自动链接发现的效率会很低,需要开发者配置一些链接规则来提高自动链接发现的效率。
也可以通过平台提供的回调函数,自己控制整个链接发现。

数据存储

数据直接存储在神箭手平台,对开发者是透明的。平台实现了较完善的数据版本控制机制,并提供了相应的规则,开发者可以通过规则来控制数据的版本。
点击这里查看详细的版本控制规则。

神箭手

基本介绍

神箭手(shenjian.io)是一个大数据和人工智能的云操作系统。您可以在神箭手上快速开发大数据和AI应用,包括爬虫/机器学习/数据清洗/API接口等。

神箭手爬虫依托于神箭手平台,使用JavaScript语言进行开发,通过配置和回调函数,来构建一个可以在神箭手平台上运行、爬取指定数据的爬虫。
一个神箭手爬虫的骨架如下:

1
2
3
var configs = {};
var crawler = new Crawler(configs);
crawler.start();

爬虫的基本设置和回调函数都定义在对象configs中,通过new Crawler(configs)来构建爬虫,最后通过start函数来启动。
神箭手爬虫开发就是通过实现不同的configs对象,来构建不同爬取目标的爬虫

主要概念

重要链接类型
  • 入口页scanUrl,这种网页一般作为爬虫的入口
  • 内容页contentUrl,这种网页承载了我们关心的数据,神箭手爬虫只在这种网页上做数据抽取。
重要待爬队列
  • scanUrl队列

此队列中存放入口页类型的链接,configs.scanUrls定义的链接会存放在此队列中,回调中可以通过site.addScanUrl添加链接到此队列中。

  • contentUrl队列

此队列中存放内容页类型的链接,自动链接发现以及site.addUrl的时候,通过正则检测来判断链接类型,如果是内容页,则链接会被加入到此队列中。

生命周期

爬虫生命周期

链接生命周期

configs对象
  • 重要属性

    • domains

      定义爬虫爬取哪些域名下的网页

    • scanUrls

      爬虫入口页链接,这是给爬虫添加入口链接的简单方式

    • contentUrlRegexes

      爬虫会根据这些正则来判断一个链接是否是内容页链接。

    • fields

      定义爬取结果的数据字段,一个field定义出一个字段。

  • 重要field对象

    • name

    • alias

    • selectorType

      抽取规则的类型。默认值是SelectorType.XPath。 可选JsonPathRegex

    • selector

      抽取规则

    • required

    • repeated

      标识当前抽取项的值是否是数组结构。默认是false。

    • children

      抽取项的子抽取项。

    • sourceType

      数据抽取源。无默认值,不设置时,抽取源默认时当前网页或父项内容。可选SourceType.UrlContextSourceType.AttachedUrl

    • attachedUrl

    • type

      标识抽取项的值类型。默认是string。支持的类型包括:int、float、image、timestamp、url、string、html、json、bool。

  • 重要回调函数

    • afterDownloadPage
重要内置对象
  • site
    • addUrl
  • page
    • raw
  • console
    • log
    • debug
    • info
重要内置函数
  • extract
  • login

爬虫实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*
神箭手云_爬虫开发
支持原生JavaScript
开发教程:http://docs.shenjian.io/develop/crawler/doc/concept/crawler.html
*/

var startPage = 1;

var configs = {
domains: ["jxsfybjy.com"],
scanUrls: ['https://www.jxsfybjy.com/nan/list_45_1.html'],
contentUrlRegexes: [/https:\/\/.*/], //内容页url正则
helperUrlRegexes: [/https:\/\/.*/], //列表页url正则 可留空
fields: [
{
name: "page",
alias: "页数",
selector: "//div[@class='listbox']/ul/li", // 3、抽取出每页评价的内容
repeated: true,
children: [
{
name: "name",
alias: "网名",
selector: "//p/text()",
required: true
}
]
}
]
};

configs.onProcessHelperPage = function(page, content, site) {
// 获取下一页列表页链接并添加到待爬队列中
startPage++;
if(startPage < 11){ // 该demo只爬取游戏排行榜前100的游戏
site.addUrl("https://www.jxsfybjy.com/nan/list_45_" + startPage + ".html");
}
return true; // 返回false表示不从当前列表页中自动发现新的链接,从而避免添加无用的链接,提高爬取速度
};

var crawler = new Crawler(configs);
crawler.start();

API接口实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
神箭手云_API接口开发
支持原生JavaScript
开发教程:http://docs.shenjian.io/develop/api/doc/concept.html
*/

var crawlUrl = 'https://search.cctv.com/ifsearch.php?qtext=%E4%BA%AC%E5%89%A7&sort=date&pageSize=20&type=video&vtime=-1' +
'&datepid=1&channel=%E4%B8%8D%E9%99%90&pageflag=0&qtext_str=%E4%BA%AC%E5%89%A7&page=1';
//@required(crawlUrl, 要爬取的地址)

var configs = {
domains: ["cctv.com"],
scanUrls: [crawlUrl],
fields: [
{
name: "page",
alias: "页数",
selector: "$.list", // 3、抽取出每页评价的内容
selectorType: SelectorType.JsonPath,
repeated: true,
children: [
{
name: "title",
alias: "标题",
selector: "$.all_title",
selectorType: SelectorType.JsonPath,
required: true
},
// {
// name: "keywords",
// alias: "关键词",
// selector: "$.keywords",
// selectorType: SelectorType.JsonPath,
// required: true
// },
// {
// name: "description",
// alias: "简介",
// selector: "$.list",
// selectorType: SelectorType.JsonPath,
// required: true
// },
{
name: "urllink",
alias: "链接",
selector: "$.urllink",
selectorType: SelectorType.JsonPath,
required : true
},
{
name: "imglink",
alias: "图片链接",
selector: "$.imglink",
selectorType: SelectorType.JsonPath,
required: true
},
{
name: "channel",
alias: "频道",
selector: "$.channel",
selectorType: SelectorType.JsonPath,
required : true
},
{
name: "playtime",
alias: "演出时间",
selector: "$.playtime",
selectorType: SelectorType.JsonPath,
required : true
},
{
name: "uploadtime",
alias: "上传时间",
selector: "$.uploadtime",
selectorType : SelectorType.JsonPath,
required : true
}
]
}
]
};

configs.afterDownloadPage = function(page, site) {
content = page.raw;
content = content.replace(/<font\s+color='red'>/g, '');
content = content.replace(/<\\\/font>/g, '');
content = JSON.parse(content);

page.raw = JSON.stringify(content);
return page;
};

var fetcher = new Fetcher(configs);
fetcher.start();

神箭手开发文档

神箭手博客