本章介绍爬虫中所有的回调函数,回调函数实际是爬虫运行过程中的一些钩子(Hook),开发者可以根据需要,来实现这些回调函数。
前面讲爬虫生命周期的时候,基本已经列出了所有的回调函数以及各自的回调点,下面逐一介绍。
initCrawl
function initCrawl(site) |
@param
site
内置对象,参考内置对象site
爬虫初始化的时候被调用,多节点运行时,只在第一个节点(又称主节点)中被调用,其他节点等待主节点的initCrawl
方法执行完之后才继续往下执行。
建议在此回调中做添加入口页的操作。
beforeCrawl
function beforeCrawl(site) |
@param
site
内置对象,参考内置对象site
initCrawl
方法之后被调用,在所有节点中都会被调用。
全局的User-Agent
设置、Cookie设置建议放到此回调函数中。
onDataReceived
function onDataReceived(data, site) |
@param
data
数据对象,Pipeline中前一个应用的数据
@param
site
内置对象,参考内置对象site
Pipeline中的爬虫通过此回调来获取前一个应用的数据,在beforeCrawl
之后被回调。
前一个应用传递过来的每条数据,会封装成一个data
对象,回调给onDataReceived
函数。
afterCrawl
function afterCrawl(site) |
@param
site
内置对象,参考内置对象site
爬虫结束时调用,每个节点都会回调,在beforeExit
之前被回调。
beforeExit
function beforeExit(site) |
@param
site
内置对象,参考内置对象site
爬虫结束时回调,只有最后一个结束的节点会回调此方法,在afterCrawl
之后被回调。
beforeDownloadPage
function beforeDownloadPage(page, site) |
@param
page
内置对象,参考内置对象page
@param
site
内置对象,参考内置对象site
@return
page
内置对象,参考内置对象page。不重写此函数时,默认返回原page
对象
当链接调度器从待爬队列中调度出来一个链接的时候,回调此函数。在此回调函数中可以修改链接地址page.url
,修改完之后需要return page
。常见的场景是链接中有时间戳,而添加链接和处理链接的时间通常是不确定的,这时可以在此回调函数中更新链接中的时间戳。
configs.beforeDownloadPage = function(page, site) { |
注意:
在此回调中网页还未开始下载,所以page.raw
是null
onChangeProxy
function onChangeProxy(site, page) |
@param
site
内置对象,参考内置对象site
@param
page
内置对象,参考内置对象page
当获取到一个新的代理的时候,回调此函数。切换代理之后,之前的cookie会被清空,一般在此回调中做一些cookie的加载。
isAntiSpider
function isAntiSpider(url, content, page) |
@param
url
当前正在处理的链接地址
@param
content
当前下载的网页内容
@param
page
内置对象,参考内置对象page
@return
boolean 是否反爬,true
表示反爬,false
表示没有反爬。不重写此函数时,默认返回false
。
每个被调度的链接下载完成之后,会先判断返回的状态码是否403,如果403,则直接会触发切换代理;如果不是403,则回调此函数,开发者一般需要在此函数中判断返回码或者网页内容,给出是否反爬的判断,如果判断为反爬,需要返回true
,否则返回false
。
configs.isAntiSpider = function(url, content, page) { |
afterDownloadPage
function afterDownloadPage(page, site) |
@param
page
内置对象,参考内置对象page
@param
site
内置对象,参考内置对象site
@return
page
内置对象,参考内置对象page。不重写此函数时,默认返回原page
对象。
每个被调度的链接下载完成之后回调该函数。在该函数中可以修改page.url
和page.raw
,修改之后,修改之后的内容会一直持续到该链接的生命周期结束。修改page.raw
后会影响后续的数据抽取,所以一般可以在这个回调函数中发一些请求,把获取的数据拼接到page.raw
中,以便后续抽取。
onProcessScanPage
function onProcessScanPage(page, content, site) |
@param
page
内置对象,参考内置对象page
@param
content
网页内容,content
与page.raw
的区别在于,content
中的链接都是绝对地址(以http开头)
@param
site
内置对象,参考内置对象site
@return
boolean 是否还需要自动发现链接,true
表示还需要自动发现,false
表示不需要自动发现。不重写此函数时,默认返回configs.autoFindUrls的值。
网页在下载完之后,如果当前链接是入口页,则回调此函数。一般在此函数中实现手动链接发现,一般是发现帮助页,也可以直接发现内容页。
onProcessHelperPage
function onProcessHelperPage(page, content, site) |
@param
page
内置对象,参考内置对象page
@param
content
网页内容,content
与page.raw
的区别在于,content
中的链接都是绝对地址(以http开头)
@param
site
内置对象,参考内置对象site
@return
boolean 是否还需要自动发现链接,true
表示还需要自动发现,false
表示不需要自动发现。不重写此函数时,默认返回configs.autoFindUrls的值。
入口页判断以及onProcessScanPage
回调之后,会继续判断当前链接是否是帮助页,如果是,则回调此函数。一般在此函数中实现手动链接发现,多数情况是发现内容页链接以及下一页帮助页的链接。
onProcessContentPage
function onProcessContentPage(page, content, site) |
@param
page
内置对象,参考内置对象page
@param
content
网页内容,content
与page.raw
的区别在于,content
中的链接都是绝对地址(以http开头)
@param
site
内置对象,参考内置对象site
@return
boolean 是否还需要自动发现链接,true
表示还需要自动发现,false
表示不需要自动发现。不重写此函数时,默认返回configs.autoFindUrls的值。
帮助页判断以及onProcessHelperPage
回调之后,会继续判断当前链接是否是内容页,如果是,则回调此函数。一般内容页不需要再做链接发现,所以此函数多数情况下直接返回false
。
onProcessXxxPage
小结:
- 这个系列的三个函数主要用来控制链接的发现,如果想要提高爬虫爬取效率,或者需要精确地控制爬虫的爬取路径,需要重点实现这三个函数,并禁用自动链接发现。
- 一个链接可能同时是入口页和帮助页,也可能同时是帮助页和内容页,甚至可能同时是入口页、帮助页和内容页,这种情况下,这个链接产生的
onProcessXxxPage
回调,必须同时都返回false
,才能禁用自动链接发现。
afterDownloadAttachedPage
function afterDownloadAttachedPage(page, site) |
@param
page
内置对象,参考内置对象page
@param
site
内置对象,参考内置对象site
@return
page
内置对象,参考内置对象page。不重写此函数时,默认返回原page
对象。
attachedUrl下载完成之后会回调此函数。可以在此函数中修改page.raw
的值,从而影响attachedUrl的后续抽取。多数场景是,attachedUrl返回的数据是jsonp格式,这时需要在此回调中把数据处理成json数据,以便后续用JsonPath
来抽取。
afterExtractField
function afterExtractField(fieldName, data, page, site, index) |
@param
fieldName
抽取项名
@param
data
当前抽取项抽取出的数据
@param
page
内置对象,参考内置对象page
@param
site
内置对象,参考内置对象site
@param
index
当前项是在父抽取项的第几个结果中进行抽取,从0开始。
@return
数据对象 返回此项对应的数据。当不重写此函数时,默认返回原data
对象。
在每个抽取项抽取到内容时回调此函数,一个网页的抽取过程中,会多次回调此函数。在此函数中,可以对抽取到的数据做进一步的处理,然后返回处理后的数据。
注意:
- 当抽取项为子项时,
fieldName
从顶层父抽取项开始,以.
拼接至当前抽取项 - 有子项的抽取项不会产生此回调
- 如果当前抽取项不是repeated的,
data
类型为String,此函数必须返回String类型;如果当前抽取项是repeated的,data
类型为String数组,则此函数必须返回String数组。
beforeHandleImg
function beforeHandleImg(fieldName, img) |
@param
fieldName
抽取项名,同afterExtractField
@param
img
一个完整的img标签
@return
String 处理后的img
在抽取的内容中发现标签时,回调此函数。一般在此函数中修改src,使src指向真实的图片地址。
beforeHostFile
function beforeHostFile(fieldName, url) |
@param
fieldName
抽取项名,同afterExtractField
@param
url
待托管的文件链接
@return
newUrl
处理后的托管链接
在托管文件之前回调此函数,在此函数中可以对文件地址做修改。常用的场景是,在图片托管中,修改链接地址来获取分辨率更高的图片。
afterHostFile
function afterHostFile(fieldName, hostedUrl) |
@param
fieldName
抽取项名,同afterExtractField
@param
hostedUrl
托管后的链接地址
在托管后的文件链接计算结束之后回调此函数,在此函数中可以对托管后的链接进行收集。
afterExtractPage
function afterExtractPage(page, data, site) |
@param
page
内置对象,参考内置对象page
@param
data
整个页面抽取出的数据
@param
site
内置对象,参考内置对象site
@return
数据对象 返回处理后的抽取数据。当不重写此函数时,默认返回原data
对象。
当整个网页完成抽取时回调此函数。一般在此回调中做一些数据整理的操作,也可以继续发送网络请求,把返回的数据整理后放到data
中返回。