下面讲的东西,都可以在官方文档中找到:https://docs.scrapy.org/en/latest/topics/request-response.html
Request对象我们早就遇到过,点进去看它的构造函数:
def __init__(self, url, callback=None, method='GET', headers=None, body=None,
cookies=None, meta=None, encoding='utf-8', priority=0,
dont_filter=False, errback=None, flags=None, cb_kwargs=None):
我们之前用到了url、callback、meta。
可以看到,也是可以设置cookies的。但实际上,scrapy有默认的middleware为我们自动添加了cookies。
里面有一个CookiesMiddleware类,里面有一个方法:
def process_request(self, request, spider):
if request.meta.get('dont_merge_cookies', False):
return
cookiejarkey = request.meta.get("cookiejar")
jar = self.jars[cookiejarkey]
cookies = self._get_request_cookies(jar, request)
for cookie in cookies:
jar.set_cookie_if_ok(cookie, request)
# set Cookie header
request.headers.pop('Cookie', None)
jar.add_cookie_header(request)
self._debug_cookie(request, spider)
里面用到的也是cookiejar,会把cookies加到header当中。
Request类中的priority参数会影响scheduler的调度顺序,越大优先级越高。
dont_filter表明是否过滤,默认时,会过滤相同的Request。
errback是出异常时的回调。
下面是Response:
Response对象的构造函数:
def __init__(self, url, status=200, headers=None, body=b'', flags=None, request=None):
headers是服务器返回的。
request就是我们之前yield出去的request。
基于这个Response,又有很多subclass(子类),TextResponse、HtmlResponse和XmlResponse。
发现HtmlResponse继承了TextResponse:
from scrapy.http.response.text import TextResponse
class HtmlResponse(TextResponse):
pass
而TextResponse是继承了Response:
class TextResponse(Response):
里面有三个比较关键的方法:
@property
def selector(self):
from scrapy.selector import Selector
if self._cached_selector is None:
self._cached_selector = Selector(self)
return self._cached_selector
def xpath(self, query, **kwargs):
return self.selector.xpath(query, **kwargs)
def css(self, query):
return self.selector.css(query)
为什么我们能对Response做xpath和css?是因为它给我们实现了selector,所以我们不需要自己去import scrapy的selector了。
通过上节课的架构图,我们知道,Request是由spider产生的,Response是由downloader产生的。看看我们的代码也知道,spider中是直接将Request yield出去,而对于Response是直接接收的,这和架构图所示是一致的。
我们不能只学会怎么用,对于一个框架,我们如果想定制化它,就必须深入源码。