一、前言
最近有个项目需要爬取药监局数据,对方有ip屏蔽机制。所以我需要在scrapy中实现ip自动切换,才能够完成爬取任务。在此之前,我先使用过第三方库scrapy-proxys加上代理api接口,可能是代码没有完善好,导致测试没有成功。 所以这次选择使用隧道的方式来测试看下,使用的是python3和scrapy库一起测试看下效果。
二、亿牛云隧道范例
亿牛云官方给出了python3和scrapy的参考示例 python3示例
代码语言:javascript复制#! -*- encoding:utf-8 -*-
import requests
import random
# 要访问的目标页面
targetUrl = "https://www.nmpa.gov.cn/"
# 要访问的目标HTTPS页面
# targetUrl = "https://www.nmpa.gov.cn/"
proxyHost = " u6791.5.tn.16yun"
proxyPort = "31111"
# 代理验证信息
proxyUser = "16EDRSSX"
proxyPass = "214575"
proxyMeta = "http://%(user)s:%(pass)s@%(host)s:%(port)s" % {
"host" : proxyHost,
"port" : proxyPort,
"user" : proxyUser,
"pass" : proxyPass,
}
# 设置 http和https访问都是用HTTP代理
proxies = {
"http" : proxyMeta,
"https" : proxyMeta,
}
# 设置IP切换头
tunnel = random.randint(1,10000)
headers = {"Proxy-Tunnel": str(tunnel)}
resp = requests.get(targetUrl, proxies=proxies, headers=headers)
print resp.status_code
print resp.text
以上是python的原本使用方式,下面提供scrapy的中间件示例 在项目中新建middlewares.py文件(./项目名/middlewares.py)
代码语言:javascript复制 #! -*- encoding:utf-8 -*-
import base64
import sys
import random
PY3 = sys.version_info[0] >= 3
def base64ify(bytes_or_str):
if PY3 and isinstance(bytes_or_str, str):
input_bytes = bytes_or_str.encode('utf8')
else:
input_bytes = bytes_or_str
output_bytes = base64.urlsafe_b64encode(input_bytes)
if PY3:
return output_bytes.decode('ascii')
else:
return output_bytes
class ProxyMiddleware(object):
def process_request(self, request, spider):
# 代理服务器(产品官网 www.16yun.cn)
proxyHost = "u6791.5.tn.16yun"
proxyPort = "31111"
# 代理验证信息
proxyUser = "16EDRSSX"
proxyPass = "214587"
request.meta['proxy'] = "http://{0}:{1}".format(proxyHost,proxyPort)
# [版本>=2.6.2](https://docs.scrapy.org/en/latest/news.html?highlight=2.6.2#scrapy-2-6-2-2022-07-25)无需添加验证头,会自动在请求头中设置Proxy-Authorization
# 版本<2.6.2 需要手动添加代理验证头
# request.headers['Proxy-Authorization'] = 'Basic ' base64ify(proxyUser ":" proxyPass)
# 设置IP切换头(根据需求)
# tunnel = random.randint(1,10000)
# request.headers['Proxy-Tunnel'] = str(tunnel)
# 每次访问后关闭TCP链接,强制每次访问切换IP
request.header['Connection'] = "Close"
三、正式集成
在项目的middlewares.py中新增类
代码语言:javascript复制import base64
proxyServer = "u6791.5.tn.16yun0"
proxyUser = "16EDRSSXxx"
proxyPass = "214587"
# for Python3
proxyAuth = "Basic " base64.urlsafe_b64encode(bytes((proxyUser ":" proxyPass), "ascii")).decode("utf8")
class ABProxyMiddleware(object):
def process_request(self, request, spider):
request.meta["proxy"] = proxyServer
request.headers["Proxy-Authorization"] = proxyAuth
四、注意总结
1,类似这样的网站在爬取过程中最好是选择稳定的固定IP,像对于scrapy这种并发度很高,又不需要登录的爬虫来说,非常合适,但是在浏览器渲染类爬虫中并不适用。 2,代理IP的速度。如果换产成是selenium来爬取,因为它采用的是浏览器渲染技术,本身速度就很慢。如果选择的代理IP速度较慢,就会大大增加爬取的时间。 3,电脑内存要够大。比如像使用chrom来获取数据,在并发度很高的情况下占内存较大。