Scrapy中间件无法采集HTTPS网站的原因
Scrapy是一个基于Python的网页抓取框架,可以帮助开发者快速高效地从网站中提取数据。 Scrapy的一个显着优势是可以通过中间件定制和优化抓取过程。中间件是一个在请求和响应之间执行特定功能的插件,例如更改用户代理、管理 cookie 和处理重定向。 Scrapy中间件还允许用户设置代理IP地址,这对于使用反抓取措施从网站抓取大量数据非常有用。使用代理IP可以隐藏用户的真实身份,避免网站访问被禁止。简而言之,Scrapy 中间件提供了一种灵活且可定制的方式来改进网页抓取过程。如果想使用代理IP,可以编写一个中间件组件,在请求对象中设置代理和认证信息,以便Scrapy使用代理和认证信息访问网页。在项目中创建一个新的 middlewares.py 文件(./projectname/middlewares.py)。以下是对应的代码:
import base64
import sys
import random
PY3 = sys.version_info[0] >= 3
def base64ify(bytes_or_str):
"""
将输入的字符串或字节数组使用 base64 进行编码,并返回编码后的结果。
如果输入为字符串,则先将其转换为字节数组。
"""
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):
"""
scrapy 的中间件,用于为每个请求添加代理。
"""
def process_request(self, request, spider):
#亿牛云爬虫加强版 代理服务器地址和端口号
proxy_host = "www.16yun.cn"
proxy_port = "31111"
#亿牛云爬虫加强版 代理服务器验证信息
proxy_username = "16YUN"
proxy_password = "16IP"
# 将请求的代理设置为指定的代理服务器
request.meta['proxy'] = "http://{0}:{1}".format(proxy_host, proxy_port)
# 为请求添加代理服务器验证头
request.headers['Proxy-Authorization'] = 'Basic ' + base64ify(proxy_username + ":" + proxy_password)
# 每次请求后关闭 TCP 连接,以强制切换 IP
request.headers['Connection'] = "Close"
上面的代码可以直接部署使用,但是有用户发现,一段时间后,目标出现在https网站上。是什么导致服务器拒绝响应?该问题发生在采集https网站时,标识“Proxy-Authorization”的认证信息会被传递到目标网站服务器。当目标服务器识别到这些信息后,就会添加反爬处理,导致爬虫请求失败。如何解决这个问题呢?从 Scrapy 2.6.2 开始,此问题已得到修复。直接设置用户的认证信息时,无需添加认证标识,请求头中自动设置“Proxy-Authorization”。这样,即使是https请求,也不会向目的Web服务器发送认证信息,避免反向爬虫。修改如下:
import base64
import sys
import random
PY3 = sys.version_info[0] >= 3
def base64ify(bytes_or_str):
"""
将输入的字符串或字节数组使用 base64 进行编码,并返回编码后的结果。
如果输入为字符串,则先将其转换为字节数组。
"""
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):
"""
scrapy 的中间件,用于为每个请求添加代理。
"""
def process_request(self, request, spider):
# 亿牛云爬虫加强版 代理服务器地址和端口号
proxy_host = "www.16yun.cn"
proxy_port = "31111"
#亿牛云爬虫加强版 代理服务器验证信息
proxy_username = "16YUN"
proxy_password = "16IP"
# [版本>=2.6.2]直接设置用户认证信息,无需添加验证头,会自动在请求头中设置Proxy-Authorization
request.meta['proxy'] = "http://{0}:{1}@{2}:{3}".format(proxyUser,proxyPass,proxyHost,proxyPort)
# 每次请求后关闭 TCP 连接,以强制切换 IP
request.headers['Connection'] = "Close"
通过上述修改,可以避免在长期采集过程中被目标网站拒绝服务。您可以使用爬虫访问https://httpbin.org/headers来测试分析用户认证信息是否得到处理。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。