scrapy中间件的使用
学习目标:
- 应用 scrapy中使用间件使用随机UA的方法
- 应用 scrapy中使用代理ip的的方法
- 应用 scrapy与selenium配合使用
1. scrapy中间件的分类和作用
1.1 scrapy中间件的分类
根据scrapy运行流程中所在位置不同分为:
- 下载中间件
- 爬虫中间件
1.2 scrapy中间的作用:预处理request和response对象
- 对header以及cookie进行更换和处理
- 使用代理ip等
- 对请求进行定制化操作,
但在scrapy默认的情况下 两种中间件都在middlewares.py
一个文件中
爬虫中间件使用方法和下载中间件相同,且功能重复,通常使用下载中间件
2. 下载中间件的使用方法:
接下来我们对腾讯招聘爬虫进行修改完善,通过下载中间件来学习如何使用中间件 编写一个Downloader Middlewares和我们编写一个pipeline一样,定义一个类,然后在setting中开启
Downloader Middlewares默认的方法:
process_request(self, request, spider)
:
- 当每个request通过下载中间件时,该方法被调用。
- 返回
None
值:没有return也是返回None,该request对象传递给下载器,或通过引擎传递给其他权重低的process_request方法
- 返回
Response
对象:不再请求,把response返回给引擎
- 返回
Request
对象:把request对象通过引擎交给调度器,此时将不通过其他权重低的process_request方法
process_response(self, request, response, spider)
:
- 当下载器完成http请求,传递响应给引擎的时候调用
- 返回Resposne:通过引擎交给爬虫处理或交给权重更低的其他下载中间件的process_response方法
- 返回Request对象:通过引擎交给调取器继续请求,此时将不通过其他权重低的process_request方法
- 在
settings.py
中配置开启中间件,权重值越小越优先执行
3. 定义实现随机User-Agent的下载中间件
3.1 在middlewares.py中完善代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| import random from Tencent.settings import USER_AGENTS_LIST
class UserAgentMiddleware(object): def process_request(self, request, spider): user_agent = random.choice(USER_AGENTS_LIST) request.headers['User-Agent'] = user_agent
class CheckUA: def process_response(self,request,response,spider): print(request.headers['User-Agent']) return response
|
3.2 在settings中设置开启自定义的下载中间件,设置方法同管道
1 2 3 4
| DOWNLOADER_MIDDLEWARES = { 'Tencent.middlewares.UserAgentMiddleware': 543, 'Tencent.middlewares.CheckUA': 600, }
|
3.3 在settings中添加UA的列表
1 2 3 4 5 6 7 8 9 10
| USER_AGENTS_LIST = [ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)", "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)", "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)", "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0", "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5" ]
|
运行爬虫观察现象
4. 代理ip的使用
4.1 思路分析
代理添加的位置:request.meta中增加proxy
字段
获取一个代理ip,赋值给request.meta['proxy']
- 代理池中随机选择代理ip
- 代理ip的webapi发送请求获取一个代理ip
4.2 具体实现
免费代理ip:
1 2 3 4 5 6 7 8 9 10
| class ProxyMiddleware(object): def process_request(self,request,spider):
proxy = 'https://1.71.188.37:3128'
request.meta['proxy'] = proxy return None
|
收费代理ip:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import base64
proxyServer = 'http://proxy.abuyun.com:9010' proxyUser = 用户名 proxyPass = 密码 proxyAuth = "Basic " + base64.b64encode(proxyUser + ":" + proxyPass)
class ProxyMiddleware(object): def process_request(self, request, spider): request.meta["proxy"] = proxyServer request.headers["Proxy-Authorization"] = proxyAuth
|
4.3 检测代理ip是否可用
在使用了代理ip的情况下可以在下载中间件的process_response()方法中处理代理ip的使用情况,如果该代理ip不能使用可以替换其他代理ip
1 2 3 4 5 6
| class ProxyMiddleware(object): ...... def process_response(self, request, response, spider): if response.status != '200': request.dont_filter = True return requst
|
在settings.py中开启该中间件
5. 在中间件中使用selenium
以github登陆为例
5.1 完成爬虫代码
1 2 3 4 5 6 7 8 9 10
| import scrapy
class Login4Spider(scrapy.Spider): name = 'login4' allowed_domains = ['github.com'] start_urls = ['https://github.com/1596930226']
def parse(self, response): with open('check.html', 'w') as f: f.write(response.body.decode())
|
5.2 在middlewares.py中使用selenium
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import time from selenium import webdriver
def getCookies(): username = input('输入github账号:') password = input('输入github密码:') options = webdriver.ChromeOptions() options.add_argument('--headless') options.add_argument('--disable-gpu') driver = webdriver.Chrome('/home/worker/Desktop/driver/chromedriver', chrome_options=options) driver.get('https://github.com/login') time.sleep(1) driver.find_element_by_xpath('//*[@id="login_field"]').send_keys(username) time.sleep(1) driver.find_element_by_xpath('//*[@id="password"]').send_keys(password) time.sleep(1) driver.find_element_by_xpath('//*[@id="login"]/form/div[3]/input[3]').click() time.sleep(2) cookies_dict = {cookie['name']: cookie['value'] for cookie in driver.get_cookies()} driver.quit() return cookies_dict
class LoginDownloaderMiddleware(object):
def process_request(self, request, spider): cookies_dict = getCookies() print(cookies_dict) request.cookies = cookies_dict
|
配置文件中设置开启该中间件后,运行爬虫可以在日志信息中看到selenium相关内容
小结
中间件的使用:
完善中间件代码:
process_request(self, request, spider)
:
- 当每个request通过下载中间件时,该方法被调用。
- 返回None值:没有return也是返回None,该request对象传递给下载器,或通过引擎传递给其他权重低的process_request方法
- 返回Response对象:不再请求,把response返回给引擎
- 返回Request对象:把request对象通过引擎交给调度器,此时将不通过其他权重低的process_request方法
process_response(self, request, response, spider)
:
- 当下载器完成http请求,传递响应给引擎的时候调用
- 返回Resposne:通过引擎交给爬虫处理或交给权重更低的其他下载中间件的process_response方法
- 返回Request对象:通过引擎交给调取器继续请求,此时将不通过其他权重低的process_request方法
需要在settings.py中开启中间件
1 2 3
| DOWNLOADER_MIDDLEWARES = { 'myspider.middlewares.UserAgentMiddleware': 543, }
|
__END__