如何为Scrapy设置代理
随着反机器人措施变得越来越流行和棘手,您的爬虫必然会遇到
Access denied
错误消息。但是,通过代理隐藏您的原始 IP 将帮助您克服这些挑战。
在这个循序渐进的教程中,您将了解有关设置 Scrapy 代理所需的一切知识。
先决条件
Scrapy 需要 Python 3.6 或更高版本,因此请确保已安装它。然后,通过pip install scrapy
在终端或命令提示符中键入来安装 Scrapy。
Scrapy 安装需要twisted-iocpsupport
,但在 Python 的最新版本(3.11.2)上不支持。因此,如果出现相关错误,请考虑保持在 3.6 和 3.10 之内。
安装完成后,就可以创建一个新的 Scrapy 项目了。为此,导航到您要存储它的目录并运行以下命令替换(ProjectName)
为您想要的名称。
scrapy startproject (ProjectName)
导航到项目目录并创建您的蜘蛛,一个用于从目标网站检索数据的 Scrapy 组件。它有两个参数:名称和目标 URL。
cd (ProjectName) scrapy genspider (SpiderName) (TargetURL)
假设您要抓取 URL https://www.example.com
。scraper
然后,您需要使用以下命令创建一个名称为 spider 的蜘蛛。
scrapy genspider scraper https://www.example.com
虽然Scrapy 支持 HTTP 和 HTTPS 代理,但可能不支持 SOCKS。自 2014 年以来开放的 GitHub 问题提供了有关此问题的更多信息。如果你想使用 SOCKS 代理,你可以探索这个问题的解决方案。
如何使用 Scrapy 设置代理
您可以通过添加元参数或创建自定义中间件来设置 Scrapy 代理。让我们探讨这两种方法。
方法一:添加元参数
此方法涉及将您的代理凭证作为方法中的元参数传递scrapy.Request()
。
获得代理地址和端口号后,使用以下语法将它们传递到 Scrapy 请求中。
yield scrapy.Request( url, callback=self.parse, meta={'proxy': 'http://proxy_address:port'} )
这是您通过更新蜘蛛得到的:
import scrapy class ScraperSpider(scrapy.Spider): name = "scraper" allowed_domains = ["www.example.com"] start_urls = ["http://www.example.com/"] for url in start_urls: yield scrapy.Request( url=url, callback=self.parse, meta={"proxy": "http://proxy_address:port"}, ) def parse(self, response): pass
现在,替换http://proxy_address:port
为您的代理凭据。您可以使用免费的在线代理提供商,例如ProxyNova和FreeProxyList。
方法 2:创建自定义中间件
Scrapy 中间件是一个拦截请求的中间层。一旦你指定了一个中间件,每个请求都会自动通过它进行路由。
对于涉及多个蜘蛛的项目来说,这是一个很好的工具,因为它允许您在不编辑或更改实际代码的情况下操纵代理凭据。
proxyMiddleware
通过扩展类并将其添加到文件来创建自定义中间件settings.py
。这是一个例子:
class CustomProxyMiddleware(object): def __init__(self): self.proxy = 'http://proxy_address:port' def process_request(self, request, spider): if 'proxy' not in request.meta: request.meta['proxy'] = self.proxy def get_proxy(self): return self.proxy
然后,将中间件添加到文件DOWNLOADER_MIDDLEWARE
中的设置中settings.py
。
DOWNLOADER_MIDDLEWARES = { 'myproject.middlewares.CustomProxyMiddleware': 350, }
您还可以使用自定义设置在蜘蛛级别添加中间件,您的代码将如下所示:
import scrapy class ScraperSpider(scrapy.Spider): name = "scraper" custom_settings = { 'DOWNLOADER_MIDDLEWARES': { 'myproject.middlewares.CustomProxyMiddleware': 350, }, } def parse(self, response): pass
请注意,myproject.middlewares
在上面的代码示例中,代表中间件类的完整模块路径。换句话说,该类是在一个名为 的 Scrapy 项目中CustomProxyMiddleware
调用的文件中定义的。middlewares.py
myproject
上面代码中的整数是指定中间件执行链的顺序号。订单号350
表示您的自定义中间件将在订单号较低的中间件之后运行。
元参数和中间件方法都可以带来相同的结果。在本教程中,我们将重点关注第二个,因为它提供了更多控制并使管理代理端点变得更加容易。
您可以利用现成的中间件包。没有必要重新发明轮子。
如何使用 Scrapy 的旋转代理
不幸的是,您仍然可以使用相同的代理被阻止,尤其是当您发出太多请求时。这是因为网站会将来自单个 IP 地址的过多请求标记为可疑,并阻止或禁止罪魁祸首。
但是,您可以通过轮换代理来避免此问题。这涉及从可用代理池中将请求分发到随机 IP,以减少被发现的机会。
那么,如何使用 Scrapy 轮换代理呢?让我们来看看!
即用型 Scrapy 代理中间件
一种选择是通过现成的 Scrapy 中间件,它会负责轮换,同时确保您使用的是活动代理。
您可以使用众多免费提供程序中的任何一个,包括scrapy-proxies、scrapy-rotating-proxies和scrapy-proxy-pool。要使用这些解决方案,请安装并启用免费中间件。然后将您的代理列表添加到settings.py
文件中。
让我们看看 scrapy-rotating-proxies 的实际应用!
使用以下命令安装它:
pip install scrapy-rotating-proxies
DOWNLOADER_MIDDLEWARE
接下来,通过将它添加到文件中的设置来启用它的中间件settings.py
。
DOWNLOADER_MIDDLEWARES = { 'scrapy_rotating_proxies.middlewares.RotatingProxyMiddleware': 350, 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 400, }
在上面的代码中,我们350
为 设置了订单号RotatingProxyMiddleware
,而内置的HttpProxyMiddleware
是400
。这确保前者首先运行,以便它可以相应地切换代理。数字是任意的,可以用唯一的整数代替。
现在是时候用你的代理创建一个文件了,每行一个,格式为protocol://ip: port
. protocol
指的是 HTTP 或 HTTPS,IP: port
是您的代理凭据。
最后,使用该ROTATING_PROXY_LIST_PATH
选项指定代理文件的路径。
ROTATING_PROXY_LIST_PATH = 'proxy_list.txt'
ROTATING_PROXY_LIST_PATH = 'proxy_list.txt'
为了测试你的 Scrapy 旋转代理,让我们抓取httpbin、ident.me和api.ipify。这些网站会记录客户端的 IP 地址,因此,如果您做的一切都正确,您的蜘蛛程序将针对每个请求返回不同的代理地址。
scraper-spider
对于这个例子,像这样更新你的:
import scrapy class ScraperSpider(scrapy.Spider): name = "scraper" def start_requests(self): urls = [ 'https://httpbin.org/ip', 'http://ident.me/', 'https://api.ipify.org?format=json', ] for url in urls: yield scrapy.Request(url=url, callback=self.parse) def parse(self, response): self.logger.info('IP address: %s' % response.text)
此外,使用以下 IP 作为您的代理列表:
{ https://23.95.94.41:3128, https://82.146.48.200:8000, https://83.171.248.156:3128 }
结果如下所示:
{ origin: "23.95.94.41"} 83.171.248.156 { ip: "82.146.48.200"}
您现在可以设置一个 Scrapy 代理并轮换多个代理以避免被阻止。
但是免费代理是不可靠的,而且大多数时候都会被阻止,所以最好使用高级网络抓取代理。让我们看一个例子!
将上面的测试目标 URL 替换为实际网站(例如Amazon )会产生以下结果,证明免费代理不起作用。
我们将在下一节中解决这个问题。
避免被阻止的最佳 Scrapy 代理工具
高级代理曾经很昂贵,尤其是对于大规模抓取,但现在您可以找到出色且负担得起的解决方案。
最好的例子之一是 ZenRows。它提供众多福利,包括代理轮换和地理位置,其灵活的定价计划起价低至每月 49 美元。
要使用 ZenRows,请注册,您将获得包含 1,000 个免费代理请求的 API 密钥。
让我们看看如何将 ZenRows 与 Scrapy 结合使用来依靠高级轮换代理服务。
方法 1:将 URL 发送到 ZenRows API 端点
为此,创建一个返回 ZenRows 代理 URL 的函数。它接受两个参数:您的 API 密钥和目标 URL。此外,urlencode
从urllib.parse
模块中导入函数以对 URL 进行编码。
import scrapy from urllib.parse import urlencode def get_zenrows_proxy_url(url, api_key): #Creates a ZenRows proxy URL for a given target_URL using the provided API key. payload = {'url': url} proxy_url = f'http://api.zenrows.com/v1/?apikey={api_key}&{urlencode(payload)}' return proxy_url
上面的代码使用与 ZenRows 代理 URL 格式链接的负载并返回proxy_url
.
让我们在 Scrapy 爬虫中使用这个函数。
首先,定义目标 URL 并添加 API 密钥。
class MySpider(scrapy.Spider): name = 'myspider' def start_requests(self): urls = [ 'http://www.amazon.com', ] api_key = 'YOUR_API_KEY' for url in urls: proxy_url = get_zenrows_proxy_url(url, api_key) yield scrapy.Request(proxy_url, callback=self.parse) def parse(self, response): # parse the response as needed self.logger.info(f"HTML content for URL {response.url}: {response.text}")
接下来,把所有东西放在一起。完整的代码应该是这样的:
import scrapy from urllib.parse import urlencode def get_zenrows_proxy_url(url, api_key): #Creates a ZenRows proxy URL for a given target_URL using the provided API key. payload = {'url': url} proxy_url = f'http://api.zenrows.com/v1/?apikey={api_key}&{urlencode(payload)}' return proxy_url class MySpider(scrapy.Spider): name = 'myspider' def start_requests(self): urls = [ 'https://www.amazon.com', ] api_key = 'API_Key' for url in urls: proxy_url = get_zenrows_proxy_url(url, api_key) yield scrapy.Request(proxy_url, callback=self.parse) def parse(self, response): # parse the response as needed self.logger.info(f"HTML content for URL {response.url}: {response.text}")
这应该是结果:
方法 2:将您的 ZenRows 凭据作为元参数传递
这种方法类似于我们之前讨论的方法。您需要做的就是在每个请求的元字段中传递您的代理详细信息。
这就是您的代码的外观:
import scrapy class ScraperSpider(scrapy.Spider): name = "scraper" start_urls = ["https://www.amazon.com"] def start_requests(self): for url in self.start_urls: yield scrapy.Request( url=url, callback=self.parse, meta={"proxy": "http://{YOUR_API_KEY}:@proxy.zenrows.com:8001"}, ) def parse(self, response): self.logger.info(f"HTML content for URL {response.url}: {response.text}")
常见问题
什么是 Scrapy 的代理?
Scrapy 的代理是一个服务器,它拦截 Scrapy 和被抓取的网站之间的请求。图书馆向代理服务器发出请求,然后代理服务器将请求转发到网站。
如何在 Scrapy 请求中使用代理?
您可以通过将代理凭据(IP、端口和身份验证详细信息)作为方法中的元参数传递来在 Scrapy 请求中使用代理Scrapy.Request()
。
什么是 Scrapy 的 IP 轮换?
Scrapy 的 IP 轮换涉及在代理服务器池中的 IP 地址之间切换,以使用 Scrapy 发出每个请求。
如何在 Scrapy 中集成代理?
您可以通过将代理凭据作为元参数传递或创建自定义中间件来在 Scrapy 中集成代理。第二个更推荐,因为它给你更多的控制权。
如何为 Scrapy 设置代理?
要为 Scrapy 设置代理,您可以将代理详细信息作为请求对象中的元参数传递,创建自定义中间件或使用免费中间件服务。