目录
中间件
控制台操作 (百度只起个名
scrapy startproject mid
scrapy genspider baidu baidu.com
setting.py内
ROBOTSTXT_OBEY =False
LOG_LEVEL ="WARNING"
运行
scrapy crawl baidu
middlewares.py 中间件
先看下载器中间件
# Not all methods need to be defined. If a method is not defined,
# scrapy acts as if the downloader middleware does not modify the
# passed objects.
重点在 process_request
在引擎将请求的信息交给下载器之前,自动的调用该方法
process_response…
process_exception 异常 (看名就知道了…)
spider_open 爬虫开始
setting.py内 DOWNLOADER_MIDDLEWARES
运行顺序
UA、代理处理—process_request
process_request 返回值有规定
- 如果返回的 None,不做拦截,继续向后面的中间件执行.(多个中间件,权重大越往后)
- 如果返回的是Request.后续的中间件将不再执行.将请求重新交给引擎.引擎重新扔给调度器
- 如果返回的是Response,后续的中间件将不再执行.将响应信息交给引擎,引擎将响应丢给spider.进行数据处理
一个请求return ;yield一群
弄2个中间件???e.g.权重544 545
UA随机
老样子:
scrapy startproject douban
cd…
scrapy genspider movie douban.com
改settingROBOTSTXT_OBEY**=False
LOG_LEVEL=**“WARNING”scrapy crawl movie
豆瓣UA 失败
setting 内有
USER_AGENT =
动态UA
可以使用useragentsring.com设置一个USER_AGENT_LIST
middlewares只留process_request即可
defprocess_request(self, request, spider):
UA = choice(USER_AGENT_LIST)
request.headers['User-Agent']= UA
returnNone
开启setting内的
DOWNLOADER_MIDDLEWARES ={"douban.middlewares.DoubanDownloaderMiddleware":543,}
代理处理
setting内
DOWNLOADER_MIDDLEWARES ={"douban.middlewares.DoubanDownloaderMiddleware":543,"douban.middlewares.ProxyDownloaderMiddleware":545,#加}
PROXY_IP_LIST ={"IP:端口","IP:端口"}
middlewares.py内
from douban.settings import PROXY_IP_LIST
from random import choice #随机......classProxyDOwnloaderMiddleware:defprocess_request(self,request,spider)
ip = choice(ProxyDOwnloaderMiddleware)
request.meta['proxy']="https://"+ip
returnNone#放行
selenium+scrapy
selenium作为下载器
由于想要替换掉原来的downloader,原中间件无意义
原最大中间价最大优先级100
DOWNLOADER_MIDDLEWARES ={"zhipin.middlewares.ZhipinDownloaderMiddleware":99,}
如果有多个spider,替换掉的下载器可能占全局
想办法适配判断是否使用selenium 处理请求
新建request.py
from scrapy import Request
classSeleniumRequest(Request):#继承Request ,导致功能与scrapy一致pass
爬虫内
from typing import Iterable
import scrapy
from zhipin.request import SeleniumRequest
classZpSpider(scrapy.Spider):
name ="zp"
allowed_domains =["zhipin.com"]
start_urls =["https://zhipin.com"]defstart_requests(self):yield SeleniumRequest(
url=self.start_urls[0],
callback=self.parse
)defparse(self, response):pass
middleware
from zhipin.request import SeleniumRequest
......defprocess_request(self, request, spider):#所有请求都回到这里#需要进行判断。判断出是否需要用selenium来处理请求#开始selenium的操作,返回页面源代码组装的response#isinstance 判断xxx , 是不是 xxx类型ifisinstance(request,SeleniumRequest):passelse:returnNonereturnNone
isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。
isinstance() 与 type() 区别:
- type() 不会认为子类是一种父类类型,不考虑继承关系。
- isinstance() 会认为子类是一种父类类型,考虑继承关系。
如果要判断两个类型是否相同推荐使用 isinstance()。
不能以原来的思路写selenium ,因为只有3个返回值–None、 Request、 Response、
封装一个响应对象
在middlewares.py 导入一个类
from scrapy.http.response.html import HtmlResponse
......defprocess_request(self, request, spider):ifisinstance(request,SeleniumRequest):
self.web.get(request.url)
page_source = self.web.page_source
return HtmlResponse(
url = request.url,
status=200,
headers=None,
body=page_source,
flags=None,
request=request,
Encoding ="utf-8")#来源于父类returnNone
版权归原作者 name_S56 所有, 如有侵权,请联系我们删除。