网络爬虫入门教程(二):configs详解

相关教程:

网络爬虫入门教程(一):概述

configs详解——之成员

爬虫的整体框架是这样:首先定义了一个configs对象,里面设置了待爬网站的一些信息,然后通过调用varcrawler=newCrawler(configs);和crawler.start();来配置并启动爬虫.

configs对象中可以定义下面这些成员

domains

定义爬虫爬取哪些域名下的网页,非域名下的url会被忽略以提高爬取速度

数组类型不能为空举个栗子:

domains:["wallstreetcn.com"],

domains:["zhihu.sogou.com","zhihu.com"],

scanUrls

定义爬虫的入口链接,爬虫从这些链接开始爬取,

同时这些链接也是监控爬虫所要监控的链接

数组类型不能为空

scanUrls的上限是1000,即爬虫每次最多处理1000个url

举个栗子:

scanUrls:["http://wallstreetcn.com/news"],

scanUrls:["http://club2011.auto.163.com/board/biaozhi308/r0a0t0g0bpeo0-n1.html","http://club2011.auto.163.com/board/fengshen/r0a0t0g0bpeo0-n1.html"],

contentUrlRegexes

定义内容页url的规则

内容页是指包含要爬取内容的网页比如http://www.qiushibaike.com/article/115878724就是糗事百科的一个内容页

数组类型正则表达式最好填写以提高爬取效率

举个栗子:

contentUrlRegexes:["http://wallstreetcn\\.com/node/\\d+"],

contentUrlRegexes:["http://club2011\\.auto\\.163\\.com/post/\\d+\\.html.*"],

特别需要注意的是,正则表达式中.和?都是需要转义的。

helperUrlRegexes

定义列表页url的规则

对于有列表页的网站,使用此配置可以大幅提高爬虫的爬取速率

列表页是指包含内容页列表的网页比如http://www.qiushibaike.com/8hr/page/2/?s=4867046就是糗事百科的一个列表页

数组类型正则表达式

举个栗子:

helperUrlRegexes:["http://wallstreetcn\\.com/news(\\?/page=\\d+)?"],

helperUrlRegexes:["http://club2011\\.auto\\.163\\.com/board/biaozhi308/r0a0t0g0bpeo0\\-n\\d+\\.html.*","http://club2011\\.auto\\.163\\.com/board/fengshen/r0a0t0g0bpeo0\\-n\\d+\\.html.*"],

fields

定义内容页的抽取规则

规则由一个个field组成,一个field代表一个数据抽取项

数组类型不能为空举个栗子:

fields:[

{

name:"content",

selector:"//*[@id='single-next-link']",

required:true

},

{

name:"author",

selector:"//div[contains(@class,'author')]//h2"

}

]

上面的例子从网页中抽取内容和作者,抽取规则是针对糗事百科的内容页写的

field在configs详解——之field中作详细介绍。

enableProxy

是否使用代理

如果爬取的网站根据IP做了反爬虫,可以设置此项为true

布尔类型可选设置举个栗子:

enableProxy:true,

interval

爬虫爬取每个网页的时间间隔

单位:毫秒

整型可选设置

interval最低设置为2000(毫秒),即2秒

举个栗子:

interval:5000,

configs详解——之field​

​field定义一个抽取项,一个field可以定义下面这些东西

name

给此项数据起个变量名。变量名中不能包含.如果抓取到的数据想要以文章或者问答的形式发布到网站(WeCenter,WordPress,Discuz!等),

field的命名请参考两个完整demo​中的命名,否则无法发布成功

String类型不能为空

举个栗子:给field起了个名字叫question

{name:"question",selector:"//*[@id='zh-question-title']/h2"}

selector

定义抽取规则,默认使用XPath

​如果使用其他类型的,需要指定selectorType

String类型不能为空

举个栗子:使用XPath来抽取知乎问答网页的问题,selector的值就是问题的XPath

{name:"question"

,selector:"//*[@id='zh-question-title']/h2"}

selectorType

抽取规则的类型

目前可用SelectorType.XPath,SelectorType.JsonPath,SelectorType.Regex

​默认SelectorType.XPath

枚举类型

栗子1:selector默认使用XPath

{name:"question"

,selector:"//*[@id='zh-question-title']/h2"//XPath抽取规则}

栗子2:selector使用JsonPath,如果内容是Json数据格式,则使用JsonPath抽取数据比较方便

{name:"question_answer_content"

,selectorType:SelectorType.JsonPath,selector:"$.comment.content",//JsonPath抽取规则required:true}

栗子3:除了XPath和JsonPath之外,神箭手还支持使用正则表达式来抽取数据

{

name:"title",

selectorType:SelectorType.Regex,

selector:'

[^\\/]+<\\/h1>'//Regex抽取规则

}

required

定义该field的值是否必须,默认false

​赋值为true的话,如果该field没有抽取到内容,该field对应的整条数据都将被丢弃

布尔类型

举个栗子:

{name:"article_title"

,selector:"//div[contains(@class,'location')]/text()[3]",required:true}

repeated

定义该field抽取到的内容是否是有多项,默认false

​赋值为true的话,无论该field是否真的是有多项,抽取到的结果都是数组结构

布尔类型

举个栗子:爬取的网页中包含多条评论,所以抽取评论的时候要将repeated赋值为true

{name:"comments"

,selector:"//*[@id='zh-single-question-page']//a[contains(@class,'zm-item-tag')]",repeated:true}

children

为此field定义子项

子项的定义仍然是一个fields结构,即一个field对象的数组没错,这是一个树形结构

数组类型

举个栗子:抓取知乎问答网页的回答,每个回答爬取了内容,作者,赞同数

{

name:"answers",

selector:"//*[@id=\"zh-question-answer-wrap\"]/div",

repeated:true,

children:[

{

name:"content",

selector:"//div[contains(@class,\"zm-editable-content\")]",

required:true

},

{

name:"author",

selector:"//a[@class=\"author-link\"]"

},

{

name:"agree_count",

selector:"//button[@class=\"up\"]/span[@class=\"count\"]"

}

]

}

sourceType​

该field的数据源,默认从当前的网页中抽取数据

选择SourceType.AttachedUrl可以发起一个新的请求,然后从请求返回的数据中抽取

选择SourceType.UrlContext可以从当前网页的url附加数据中抽取

url附加数据后面会作介绍

枚举类型

attachedUrl

当sourceType设置为SourceType.AttachedUrl时,定义新请求的url

String类型

举个栗子:当爬取的网页中某些内容需要异步加载请求时,就需要使用attachedUrl,比如,抓取知乎回答中的评论部分,就是通过AJAX异步请求的数据

{

name:"comment_id",

selector:"//div/@data-aid",

},

{

name:"comments",

sourceType:SourceType.AttachedUrl,

//"comments"是从发送"attachedUrl"这个异步请求返回的数据中抽取的

//"attachedUrl"支持引用上下文中的抓取到的"field",这里就引用了上面抓取的"comment_id"

attachedUrl:"https://www.zhihu.com/r/answers/{comment_id}/comments",

selectorType:SelectorType.JsonPath,

selector:"$.data",

repeated:true,

children:[

...

]

}

UrlContext

当sourceType赋值为SourceType.UrlContext时,表示从内容页中的附加数据(是开发者自定义的一段代码,例如,html代码)中抽取数据

String类型

举个栗子:将自定义数据附加到内容页中,然后再提取到field

varconfigs={

//configs中的其他成员

...

fields:[

{

name:"extra_data",

//这里是从开发者附加的一段html代码中抽取的数据

sourceType:SourceType.UrlContext,

selector:"//span[contains(@class,'shenjianshou')]",

}

]

};

configs.onProcessHelperPage=function(page,content,site){

//定义附加数据

varextraData='

100

';

//将extraData附加到contentUrl对应的网页中,将contentUrl添加到待爬队列中

site.addUrl(contentUrl,"get",null,extraData);

...

returnfalse;

}

transient

定义该field是否被移除,默认false

​赋值为true的话,在调用afterExtractPage回调函数(在configs详解——之回调函数中会详细描述)后,才会移除包含transient字段的field

布尔类型

举个栗子:爬取的数据中要移除某个field时,要将transient赋值为true

{

name:"avatar",

selector:"//div[contains(@class,'bbs_detail_item')][1]//a[1]/img",

transient:true

}

configs详解——之site,page和consolesite

​site

site表示当前正在爬取的网站的对象,下面介绍了可以调用的函数

site.addHeader(key,value)

一般在beforeCrawl回调函数(在configs详解——之回调函数中会详细描述)中调用,用来添加一些HTTP请求的Header

@paramkeyHeader的key,如User-Agent,Referer等

@paramvalueHeader的值

举个栗子:

Referer是HTTP请求Header的一个属性,http://buluo.qq.com/p/index.html是Referer的值

configs.beforeCrawl=function(site){

site.addHeader("Referer","http://buluo.qq.com/p/index.html");

}

site.addCookie(key,value)

一般在beforeCrawl回调函数(在configs详解——之回调函数中会详细描述)中调用,用来添加一些HTTP请求的Cookie

@paramkeyCookie的key

@paramvalueCookie的值

举个栗子:

cookie是由键-值对组成的,BAIDUID是cookie的key,FEE96299191CB0F11954F3A0060FB470:FG=1则是cookie的值

configs.beforeCrawl=function(site){

site.addCookie("BAIDUID","FEE96299191CB0F11954F3A0060FB470:FG=1");}

site.addCookies(cookies)

一般在beforeCrawl回调函数(在configs详解——之回调函数中会详细描述)中调用,用来添加一些HTTP请求的Cookie

@paramcookies多个Cookie组成的字符串

举个栗子:

cookies是多个cookie的键-值对组成的字符串,用;分隔。BAIDUID和BIDUPSID是cookie的key,FEE96299191CB0F11954F3A0060FB470:FG=1和FEE96299191CB0F11954F3A0060FB470是cookie的值,键-值对用=相连

configs.beforeCrawl=function(site){

site.addCookies("BAIDUID=FEE96299191CB0F11954F3A0060FB470:FG=1;BIDUPSID=FEE96299191CB0F11954F3A0060FB470;");

​site.addUrl(url,options)

一般在onProcessScanPage和onProcessHelperPage回调函数(在configs详解——之回调函数中会详细描述)中调用,用来往待爬队列中添加url

@paramurl待添加的url

@paramoptionsjavascript对象,成员包括method、data、contextData、headers和reserve,如下所示:

@paramoptions.method默认为"GET"请求,也支持"POST"请求

@paramoptions.data发送请求时需添加的参数,可以为空

@paramoptions.contextData此url附加的数据,可以为空

@paramoptions.headers此url的Headers,可以为空

@paramoptions.reserve此url是否去重,默认为false(设置为false,表示之前处理过的url不再插入待爬队列;设置为true,表示之前处理过的url也会插入待爬队列)

兼容之前版本site.addUrl(url,method,data,contextData)

栗子1:

configs.onProcessHelperPage=function(page,content,site){

varregex=/https?:\\\/\\\/www\.jiemian\.com\\\/article\\\/\d+\.html/g;

varurls=[];

urls=content.match(regex);

if(urls!=""){

for(vari=0,n=urls.length;i<n;i++){

urls[i]=urls[i].replace(/\\/g,"");

//get请求,未添加options对象

site.addUrl(urls[i]);

}

}

...

returnfalse;

}

栗子2:

configs.onProcessHelperPage=function(page,content,site){

...

varnextUrl=page.url.replace("page="+currentPageNum,"page="+pageNum);

//定义"options"对象,包括"method"和"data"两个成员

varoptions={

method:"POST",

data:{

page:pageNum,

size:18

}

};

//post请求,添加options对象

site.addUrl(nextUrl,options);

returnfalse;

site.requestUrl(url,options)

一般在beforeCrawl,afterDownloadPage,onProcessScanPage和onProcessHelperPage回调函数(在configs详解——之回调函数中会详细描述)中调用,下载网页,得到网页内容

@paramurl待下载的url

@paramoptionsjavascript对象,成员包括method、data和headers,如下所示:

@paramoptions.method默认为"GET"请求,也支持"POST"请求

@paramoptions.data发送请求时需添加的参数,可以为空

@paramoptions.headers此url的Headers,可以为空

兼容之前版本site.requestUrl(url,method,data)

举个栗子:

configs.afterDownloadPage=function(page,site){

varurl="https://checkcoverage.apple.com/cn/zh/?sn=FK1QPNCEGRYD";

//定义"options"对象,包括"method"和"data"两个成员

varoptions={

method:"POST",

data:{

sno:"FK1QPNCEGRYD",

CSRFToken:result[1]

}

};

//通过发送带参数的POST请求,下载网页,并将网页内容赋值给result

varresult=site.requestUrl(url,options);

...

returnpage;

}

site.setUserAgent(userAgent)

一般在beforeCrawl等回调函数(在configs详解——之回调函数中会详细描述)中调用,设置浏览器userAgent

@paramuserAgent需添加的userAgent

默认使用userAgent:Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/47.0.2526.106Safari/537.36

查看“常见浏览器userAgent大全”

举个栗子:

configs.beforeCrawl=function(site){

varuserAgent="Mozilla/4.0(compatible;MSIE6.0;)Opera/UCWEB7.0.2.37/28/";

site.setUserAgent(userAgent);

}

page

page表示当前正在爬取的网页页面的对象,下面介绍了可以调用的变量和函数

page.url

当前正在爬取的网页页面的url

举个栗子:

在afterExtractPage回调函数(在configs详解——之回调函数中会详细描述)中,将url值赋给名叫article_content的field

configs.afterExtractPage=function(page,data){

data.article_content=page.url+"";

returndata;

}

​page.raw

当前网页原始内容

举个栗子:

在onProcessScanPage回调函数(在configs详解——之回调函数中会详细描述)中,通过page.raw得到网页原始内容,然后转换成Json对象

configs.onProcessScanPage=function(page,content,site){

varjsonObj=JSON.parse(page.raw);

...

returnfalse;

}

page.skip(fieldName)

一般在afterExtractField回调函数(在configs详解——之回调函数中会详细描述)中使用,用来忽略当前网页的抽取结果或当前上下文的一条结果

@paramfieldName根据fieldName来确定忽略范围,可以为空。当为空时,忽略当前网页的抽取结果

栗子1:

例如爬取知乎问答的时候,想只爬取话题中包含经济学的问答,可以这样过滤:

configs.afterExtractField=function(fieldName,data){

if(fieldName=="topics"){//fieldName是topics

if(data.indexOf("经济学")==-1){//data中不包含"经济学"

page.skip();//跳过当前爬取的网页

}

}

returndata;

}

​栗子2:

例如爬取知乎问答的时候,想要只爬取赞同数大于10的回答,可以这样过滤:

configs={

//configs中的其他成员

...

fields:[

{

name:"answers",

selector:"//*[@id=\"zh-question-answer-wrap\"]/div",

repeated:true,

children:[

{

name:"agree_count",

selector:"//button[@class=\"up\"]/span[@class=\"count\"]"

},

...

]

}

]

};

configs.afterExtractField=function(fieldName,data,page){

if(fieldName=="answers.agree_count"){//fieldName是answers数组中的agree_count元素名

if(parseInt(data)<10){//回答的点赞数小于10

page.skip("answers");//跳过这个回答

}

}

returndata;

}

console

console对象提供不同级别的日志打印

console.log(message)

打印日志,调试时使用

举个栗子:

console.log("测试log日志");

console.debug(message)

打印出错级别日志,调试时使用

举个栗子:

console.debug("正在提取文章标题数据");

console.info(message)

打印普通日志

举个栗子:

console.info("成功处理一个页面");

console.warn(message)

打印警告情况的日志

举个栗子:

console.warn("XX文件解析失败");

console.error(message)

打印错误情况的日志

举个栗子:

console.error("XPath错误");

​configs详解——之回调函数

回调函数是在爬虫爬取并处理网页的过程中设置的一些系统钩子,通过这些钩子可以完成一些特殊的处理逻辑.

回调函数需要设置到configs参数里面才起作用

下图是神箭手云爬虫爬取并处理网页的流程图,矩形方框中标识了爬虫运行过程中所使用的重要回调函数:

beforeCrawl(site)

爬虫初始化时调用,用来指定一些爬取前的操作

@paramsite当前正在爬取的网站的对象

在函数中可以调用site.addHeader(key,value),site.addCookie(key,value),site.addCookies(cookies)等

举个栗子:

在爬虫开始爬取之前给所有待爬网页添加一个Header

configs.beforeCrawl=function(site){

site.addHeader("Referer","http://buluo.qq.com/p/index.html");

}

isAntiSpider(url,content)

判断当前网页是否被反爬虫了,需要开发者实现

@paramurl当前网页的url

@paramcontent当前网页内容

@return如果被反爬虫了,返回true,否则返回false

举个栗子:

configs.isAntiSpider=function(url,content){

if(content.indexOf("404页面不存在")>-1){//content中包含"404页面不存在"字符串

returntrue;//返回当前网页被反爬虫了

}

returnfalse;

}

afterDownloadPage(page,site)

在一个网页下载完成之后调用.主要用来对下载的网页进行处理.

@parampage当前下载的网页页面的对象,调用page.url可获取当前网页的url,调用page.raw可获取当前网页内容

@paramsite当前正在爬取的网站的对象

@return返回处理后的网页

举个栗子:

比如下载了某个网页,希望向网页的body中添加html标签,处理过程如下:

configs.afterDownloadPage=function(page,site){

varpageHtml="5";

varindex=page.raw.indexOf("");

page.raw=page.raw.substring(0,index)+pageHtml+page.raw.substring(index);

returnpage;

}

onProcessScanPage(page,content,site)

在爬取到入口url的内容之后,添加新的url到待爬队列之前调用.主要用来发现新的待爬url,并且能给新发现的url附加数据.

@parampage当前正在爬取的网页页面的对象,调用page.url可获取当前网页的url,调用page.raw可获取当前网页内容,调用page.skip()便不再爬取当前网页

@paramcontent当前网页内容

@paramsite当前正在爬取的网站的对象

@return返回false表示不需要再从此网页中发现待爬url

此函数中通过调用site.addUrl(url,options)函数来添加新的url到待爬队列。

栗子1:

实现这个回调函数并返回false,表示爬虫在处理这个scanUrl的时候,不会从中提取待爬url

configs.onProcessScanPage=function(page,content,site){

returnfalse;

}

栗子2:

生成一个新的url添加到待爬队列中,并通知爬虫不再从当前网页中发现待爬url

configs.onProcessScanPage=function(page,content,site){

varjsonObj=JSON.parse(page.raw);

for(vari=0,n=jsonObj.data.length;i<n;i++){

varitem=jsonObj.data[i];

varlastid=item._id;

//生成一个新的url

varurl=page.url+lastid;

//将新的url插入待爬队列中

site.addUrl(url);

}

//通知爬虫不再从当前网页中发现待爬url

returnfalse;

}

onProcessHelperPage(page,content,site)

在爬取到列表页url的内容之后,添加新的url到待爬队列之前调用.主要用来发现新的待爬url,并且能给新发现的url附加数据.

@parampage当前正在爬取的网页页面的对象,调用page.url可获取当前网页的url,调用page.raw可获取当前网页内容,调用page.skip()便不再爬取当前网页

@paramcontent当前网页内容

@paramsite当前正在爬取的网站的对象

@return返回false表示不需要再从此网页中发现待爬url

此函数中通过调用site.addUrl(url,options)函数来添加新的url到待爬队列

栗子1:

实现这个回调函数并返回false,表示爬虫在处理这个helperUrl的时候,不会从中提取待爬url

configs.onProcessHelperPage=function(page,content,site){

returnfalse;

}

栗子2:

在onProcessHelperPage回调函数中,生成新的contentUrl并添加到待爬队列中,并通知爬虫不再从当前网页中发现待爬url

configs.onProcessHelperPage=function(page,content,site){

varjsonObj=JSON.parse(content);

varid=0;

for(vari=0,n=jsonObj.data.length;i<n;i++){

varitem=jsonObj.data[i];

id=item._id;

//将新的url插入待爬队列中

site.addUrl("http://service.chanjet.com/api/v1/message/"+id);

}

//通知爬虫不再从当前网页中发现待爬url

returnfalse;

}

beforeHandleImg(fieldName,img)

在抽取到field内容之后调用,对其中包含的img标签进行回调处理

@paramfieldName当前field的name.注意:子field的name会带着父field的name,通过.连接.

@paramimg整个img标签的内容

@return返回处理后的img标签的内容

很多网站对图片作了延迟加载,这时候就需要在这个函数里面来处理

举个栗子:

汽车之家论坛帖子的图片大部分是延迟加载的,默认会使用http://x.autoimg.cn/club/lazyload.png图片url,我们需要找到真实的图片url并替换,具体实现如下:

configs.beforeHandleImg=function(fieldName,img){

//通过正则判断img中的src属性是不是真实图片url,如果是,则直接返回img,如果不是,继续执行

varregex=/src="(https?:\/\/.*?)"/;

varrs=regex.exec(img);

if(!rs)returnimg;

varurl=rs[1];

if(url=="http://x.autoimg.cn/club/lazyload.png"){

varregex2=/src9="(https?:\/\/.*?)"/;

rs=regex2.exec(img);

//替换成真实图片url

if(rs){

varnewUrl=rs[1];

img=img.replace(url,newUrl);

}

}

returnimg;

}

beforeCacheImg(fieldName,url)

由于很多网站都有图片防盗链限制,所以神箭手会缓存爬到的图片,在缓存之前,可以对图片作处理

@paramfieldName当前field的name.注意:子field的name会带着父field的name,通过.连接.

@paramurl图片的url

@return处理后的图片url

举个栗子:

知乎问答页面,用户的头像链接是这样的:https://pic3.zhimg.com/xxxxxx_s.jpg

研究一下可以发现,大一点的头像是这样的:https://pic3.zhimg.com/xxxxxx_l.jpg

configs.beforeCacheImage=function(fieldName,url){

if(fieldName=="answers.avatar"){

returnurl.replace("_s.jpg","_l.jpg");//对url进行字符串替换,得到较大图片的url

}

returnurl;//返回图片url

}

afterExtractField(fieldName,data,page)

当一个field的内容被抽取到后进行的回调,在此回调中可以对网页中抽取的内容作进一步处理

@paramfieldName当前field的name.注意:子field的name会带着父field的name,通过.连接.

@paramdata当前field抽取到的数据.如果该field是repeated,data为数组类型,否则是String

@parampage当前正在爬取的网页页面的对象,调用page.url可获取当前网页的url,调用page.skip()便不再爬取当前网页

@return返回处理后的数据,注意数据类型需要跟传进来的data类型匹配

举个栗子:

比如爬取知乎用户的性别信息,相关网页源码如下:

那么可以这样写:

configs={

//configs的其他成员

...

fields:[

{

name:"gender",

selector:"//span[contains(@class,'gender')]/i/@class"

}

]

...

};

configs.afterExtractField=function(fieldName,data,page){

if(fieldName=="gender"){

if(data.indexOf("icon-profile-male")>-1){//data中包含"icon-profile-male",说明当前知乎用户是男性

return"男";

}

elseif(data.indexOf("icon-profile-female")>-1){//data中包含"icon-profile-female",说明当前知乎用户是女性

return"女";

}

else{//data未匹配到上面的两个字符串,无法判断用户性别

return"未知";

}

}

returndata;

}

afterExtractPage(page,data)

在一个网页的所有field抽取完成之后,可能需要对field进一步处理,以发布到自己的网站

@parampage当前正在爬取的网页页面的对象,调用page.url可获取当前网页的url,调用page.skip()便不再爬取当前网页

@paramdata当前网页抽取出来的所有field的数据,JavaScript对象

@return返回处理后的数据,注意数据类型不能变

举个栗子:

比如从某网页中得到time和title两个field抽取项,现在希望把time的值添加中括号后拼凑到title中,处理过程如下:

configs.afterExtractPage=function(page,data){

vartitle="["+data.time+"]"+data.title;

data.title=title;

returndata;

}

nextScanUrl(url)

在处理完待爬队列中的url后,生成下一个scanUrl并插入到待爬队列中

@paramurl当前的scanUrl

@return返回下一个scanUrl或返回null

举个栗子:

某个网站有1500个scanUrl,需先处理前1000个scanUrl,再调用nextScanUrl回调函数来逐个处理后面500个,处理过程如下:

//增加1000个"scanUrl",一个爬虫最多一次性处理1000个"scanUrl"

for(vari=1;i<=1000;i++){

scanUrls.push("http://www.dianping.com/search/keyword/"+i+"/0_"+keywords);

}

varconfigs={

//"configs"的其他成员

...

scanUrls:scanUrls,

...

};

configs.nextScanUrl=function(url){

varcurrentPage=url.substring(url.indexOf("keyword/")+8,url.indexOf("/0_"));

//页面数超过1500以后,返回空值

if(currentPage>1500){

returnnull;

}

else{

varnextPage=currentPage+1;

varnextScanUrl=url.replace("keyword/"+currentPage,"keyword/"+nextPage);

//将下一个"scanUrl"插入待爬队列

returnnextScanUrl;

}

};

对爬虫感兴趣的童鞋可以加腾讯群讨论:342953471。

相关推荐