您的位置:首页 > 其它

Scrapy手动增加Add Cookie和关掉重复过滤器dupfilters

2017-07-20 17:48 225 查看
Scrapy 本身是能够处理Cookie的, 工作原理和浏览器类似

浏览器发送请求

服务器返回响应, 并使用Set-Cookie来要求浏览器再下一次的请求中, 带上Cookie

下一次请求, 浏览器在请求头中使用Cookie带上上一次服务器要求设置的Cookie

整个流程无需人工干预, 由浏览器自动完成.

在Scrapy中, 这个也是无需干预的, 其功能在CookieMiddleware中自动完成

使用的方法就是:

1. settings.py中打开开关

COOKIES_ENABLED=True

COOKIES_DEBUG=True #这个是在log中能看到每次请求发出了和接收到什么Cookie

2. 运行你的爬虫即可

那么, 问题来了, 怎么手动带上额外的Cookie呢?

翻了很多文档和源码, 特总结如下

带上Cookie, 一定是在Request上操作的, 所以, 不要去翻Response的源码了.

Request有2个方法

1) Request, FormRequest

2) response.follow(…) #这个执行完了, 会返回一个Request对象

3. 为什么会要手动添加一个Cookie

答案就是现在的网页很多都用js来给document添加cookie

比如document.cookie=’person=zhouxingchi’;

这个在网页上, 由js添加的cookie, 再下一次请求的时候, 如果使用浏览器, 是可以带到下一个请求中的.

但是在scrapy里, 因为获取的是源码, 故js无法执行, 所以, 要求开发人员手动为下一个请求添加上该cookie.

4. 如何手动添加cookie

看了好多的源码, 文档, 和示例, 终于搞清楚了.

第一步: 修改start_requests, 启用meta的meta[‘cookiejar’]

def start_requests(self):
for url in self.start_urls:
yield Request(url,
meta={'cookiejar': 'mysitecom'},
callback=self.parse
)


第二步, 请求req的时候, 带上meta[‘cookiejar’]

def parse(self, response):
req = response.follow(response.url, self.parse_nextpage)
#或者
#req = Request(url, self.parse_nextpage)
req.meta['cookiejar'] = response.meta['cookiejar']
#同时, 更新request.cookies(一个类似与字典的)
req.cookies.update({'person': 'zhouxingchi'})
yield req


如此, 就加上cookie了, 这个req被yield 之后, 就能带上person这个cookie, 发起请求了.

5. 额外提示, 关于关闭重复过滤器dupfilters

如果第4步中的url, 已经请求过一次了, 那么, 再次提交yield req(url), 就会在日志中看到

msg = ("Filtered duplicate request: %(request)s"
" - no more duplicates will be shown"
" (see DUPEFILTER_DEBUG to show all duplicates)")


也就是说, 访问url前, 你没有cookie, 加上cookie之后, 你被scrapy的重复链接过滤器Scrapy的DUPEFILTER_CLASS = ‘scrapy.dupefilters.RFPDupeFilter’ 过滤掉了, 悲催的很.

那么, 最简单的想法就是关掉这个重复过滤器啊.

scrapy的源码翻了一遍, 发现无法关掉这个东西.

但是找到一个控制的地方.

答案就在 scrapy/core/scheduler.py 的如下函数:

def enqueue_request(self, request):
if not request.dont_filter and self.df.request_seen(request):
self.df.log(request, self.spider)
return False
dqok = self._dqpush(request)
if dqok:
self.stats.inc_value('scheduler/enqueued/disk', spider=self.spider)
else:
self._mqpush(request)
self.stats.inc_value('scheduler/enqueued/memory', spider=self.spider)
self.stats.inc_value('scheduler/enqueued', spider=self.spider)
return True


request.dont_filter 默认为False, 这个可以在Request的定义文件中发现

class Request(object_ref):

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):


所以, 去掉重复过滤器无望的情况下, 可以先在Request的初始化函数中, 传入dont_filter=True.

就是这样:

def parse(self, response):
req = Request.follow(response.url, self.parse_nextpage, dont_filter=True)
req.meta['cookiejar'] = response.meta['cookiejar']
req.cookies.update({'person': 'zhouxingchi'})
yield req


完毕.

有任何问题请加入以下群来交流, 发广告直接踢哦:

Python爬虫群 10255808

Python爬虫2群 429348027
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息