diff --git "a/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/5\347\217\255/5\347\217\255_\344\272\221/week_11/Scrapy-Meta\344\277\241\346\201\257\344\274\240\351\200\222_\350\207\252\345\256\232\344\271\211_\345\274\202\345\270\270\345\244\204\347\220\206-11-2noteyun.md" "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/5\347\217\255/5\347\217\255_\344\272\221/week_11/Scrapy-Meta\344\277\241\346\201\257\344\274\240\351\200\222_\350\207\252\345\256\232\344\271\211_\345\274\202\345\270\270\345\244\204\347\220\206-11-2noteyun.md" new file mode 100644 index 0000000000000000000000000000000000000000..4c53b10199299611248c172bbf2c1dd27f9a94e6 --- /dev/null +++ "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/5\347\217\255/5\347\217\255_\344\272\221/week_11/Scrapy-Meta\344\277\241\346\201\257\344\274\240\351\200\222_\350\207\252\345\256\232\344\271\211_\345\274\202\345\270\270\345\244\204\347\220\206-11-2noteyun.md" @@ -0,0 +1,163 @@ +11-2noteyun- + +# Meta + +## 信息传递 + +- 在创建`REQEUSTS`对象时设置meta + + ``` + #通过meta进行信息传递 + yield scrapy.FormRequest(meta={"keyword": keyword, "sta_date": sta_date}) + ``` + +- 在`REQUESTS`对象流转中修改meta + + - download_slot + - download_latency + + + + + +- 在`RESPONSE`对象中获取meta + + ```python + #等同于response.request.meta + response.meta + ``` + +image-20210313194634648![image-20210313195127149](C:\Users\yunqin\AppData\Roaming\Typora\typora-user-images\image-20210313195127149.png) + +image-20210313195127149 + + + +image-20210313200037968 + +## 自定义单个请求的配置 + +https://docs.scrapy.org/en/latest/topics/request-response.html?highlight=meta#topics-request-meta + +```python +https://docs.scrapy.org/en/latest/topics/request-response.html?highlight=meta#topics-request-meta +``` + +- `dont_redirect` + + 如果设置为`True`, 当前请求则不会重定向. + +- `dont_retry` + + 如果设置为`True`, 当前请求则不会重试. + +- `max_retry_times` + + 设置最大重试次数. + +- `dont_merge_cookies` 和 `cookiejar` + + 操作cookie的meta参数, 但是不建议这么使用, 一般来说我们直接设置 + + ```python + request.headers["cookie"] = "......." + ``` + +- `proxy` + + 设置请求代理 + + ```python + request.meta['proxy'] = '127.0.0.1:8989' + ``` + +- 设置优先级 + + 如果你设置了优先级队列, 那么可以只是`priority`参数决定请求的顺序 + + ```python + # 数字越小, 优先级越高 + request.meta['priority'] = 10 + ``` + +image-20210313203948835 + +# 异常处理 + +> 异常处理时scrapy最大的痛点, 因为你一定要熟悉事件的流向. + +## Spiders组件 + +在异常处理中, Spider组件其实是处理`RESPONSE`对象或者请求之后产生的异常, **一般**作为一次请求异常处理的终点, 也就是指定的回调函数`errorback`. + +- errorback + + 处理不可控的异常 + + ```python + def start_request(self): + yield scrapy.FormRequest(errorback=self.process_error) + + def process_error(self, failure): + print(failure) + # 记录异常 + # 发送通知 + # 重做任务 + ... + ``` + + - failure.request + + 当前异常请求对象 + + - failure.value + + 当前的异常对象 + +- CloseSpider + + 遇到像cookie过期, 账号警告, 代理池空了这样严重的错, 需要关闭实例, 可抛出CloseSpider异常, 该异常最终会流向`ENGINE`后关闭爬虫实例. + + ```python + from scrapy.exceptions import CloseSpider + ``` + +## 中间件 + +处理可控的异常 + +```python +def process_exception(self, request, exception, spider): + pass +``` + +- 返回None + + 由下一层中间件继续处理, 如果你指定了`errback`, 最终会到达`errback` + +- 返回`REPONSE`对象 + + 中断异常链, 返回的`RESPONSE`对象会到达`Spiders`组件 + +- 返回`Request` + + 中断异常链, 返回的`Request`对象将到达`ENGINE`由`SCHEDULER`重新调度. + + ```python + def process_exception(self, request, exception, spider): + # 如果异常是cookie池空了, 可以在这里完成cookie池的补充 + # 补充cookie池 + if isinstance(exception, IndexError): + # 我已经知道异常产生原因, 所以免除当前重试次数的计数 + retry_times = request.meta.get('retry_times', 1) + request.meta['retry_times'] = retry_times - 1 + return request + ``` + +# 课后作业 + +- 尝试在中间件当中处理异常 +- 尝试在中间件中抛出异常, 由Spiders组件中的errorback来处理. + + +