Spider¶
用户自定义的spider需要继承 xpaw.spider.Spider
,并重写如下函数:
start_requests()
:返回初始入口URL构成的HttpRequest
。parse()
:返回从爬取的网页中提取出所需的数据和后续待爬取的HttpRequest
。
Note
parse()
是默认处理 HttpResponse
的函数,如果在每个生成的 HttpRequest
中都通过 callback
指定了相应的处理函数 ,也可以不重写该函数。
Spider API¶
-
class
xpaw.spider.
Spider
¶ 用户自定义的spider需要继承此类。
-
classmethod
from_crawler
(crawler)¶ Parameters: crawler (Crawler) – crawler crawler通过该函数实例化spider,在该函数中会调用spider的构造器
-
logger
¶ 提供纪录日志的logger。
-
log
(message, *args, level=logging.INFO, **kwargs)¶ 通过logger纪录日志。
-
start_requests
()¶ 生成初始请求
Returns: HttpRequest
的可迭代对象。
-
parse
(response)¶ 解析爬取结果
Parameters: response (HttpResponse) – 爬取结果。 Returns: 可迭代对象,可以是新的请求 HttpRequest
,和提取的数据Item
、dict
等。
-
open
()¶ 爬虫开始工作前会调用该函数。
-
close
()¶ 爬虫完成工作时会调用该函数。
-
classmethod
Parsing Data to Callback Functions¶
我们可以通过 HttpRequest
的 callback
指定spider的某个成员函数来处理得到的 HttpResponse
。
例如:
def parse_index_page(self, response):
yield xpaw.HttpRequest("http://www.example.com/some_page.html",
callback=self.parse_some_page)
def parse_some_page(self, response):
# handle the response of "http://www.example.com/some_page.html"
self.log('Visited: %s', response.url)
有些时候,我们同时想传递一些和 HttpRequest
相关的参数并能够在callback函数中获取到。
例如,我们可能希望纪录父级页面的URL,即是由哪个页面跳转而来的。
我们可以通过 HttpRequest
的 meta
实现参数的传递。
以下是一个纪录父级页面的URL的示例:
def parse_index_page(self, response):
request = xpaw.HttpRequest("http://www.example.com/some_page.html",
callback=self.parse_some_page)
request.meta['referer'] = response.url
yield request
def parse_some_page(self, response):
self.log('Visited: %s', response.url)
self.log('Referer: %s', response.meta['referer'])
Note
HttpResponse
的meta
属性即为对应HttpRequest
的meta
属性。- 在使用
HttpRequest
的meta
传递参数时,请避免和中间件使用的关键字冲突。
Request Error Handling in Errback Functions¶
我们可以通过 HttpRequest
的 errback
指定spider的某个成员函数来处理请过程中出现的异常。
下面给出了一个区分不同的异常并进行处理的示例:
class ErrorHandlingSpider(Spider):
start_urls = [
"http://www.python.org/", # 200 OK
"http://www.httpbin.org/status/404", # 404 Not Found
"http://www.httpbin.org/status/500", # 500 Service Not Available
"http://unknown/", # ClientError
]
def start_requests(self):
for url in self.start_urls:
yield HttpRequest(url, errback=self.handle_error)
def parse(self, response):
self.logger.info('Successful response: %s', response)
def handle_error(self, request, error):
if isinstance(error, HttpError):
response = error.response
self.logger.error('HttpError on %s: HTTP status=%s', request.url, response.status)
elif isinstance(error, ClientError):
self.logger.error('ClientError on %s: %s', request.url, error)
if __name__ == '__main__':
run_spider(ErrorHandlingSpider, retry_enabled=False)