Python爬虫框架Scrapy代理中间件掌握学习教程
在进行爬虫开发时,经常需要使用代理来避免IP被封锁或者提高爬取效率。而Scrapy是一个功能强大的Python爬虫框架,也提供了代理中间件这一强大的功能以支持代理。
代理中间件的使用方法
Scrapy提供了一个内置的代理中间件,可以通过在项目设置中设置代理中间件的位置及相应的参数,来让Scrapy使用代理。
以下是在Scrapy项目的settings.py中加入代理中间件的配置方法:
DOWNLOADER_MIDDLEWARES = {
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None, #禁用默认的代理中间件
'scrapy_proxy_pool.middlewares.ProxyPoolMiddleware': 610, #启用代理池中间件
'scrapy_proxy_pool.middlewares.BanDetectionMiddleware': 620, #启用ban检测中间件
}
# scrapy-proxy-pool是一个常用的代理池,可通过pip安装
PROXY_POOL_ENABLED = True
以上配置中,我们禁用了Scrapy默认的代理中间件(内置的HttpProxyMiddleware和RetryMiddleware),启用了第三方的代理池中间件scrapy-proxy-pool,并设置了其在下载器中的顺序。
需要注意的是,要在使用代理之前先安装代理池模块 scrapy-proxy-pool
。
示例1:使用代理IP池来爬取网站
假设我们要使用代理来爬取一个目标网站,我们可以创建一个新的scrapy项目进行实验。以下是项目的目录结构(省略了一些不必要的文件和目录):
scrapy-proxy-example/
scrapy.cfg
proxy_example/
__init__.py
items.py
middlewares.py
pipelines.py
settings.py
spiders/
__init__.py
my_spider.py
首先,我们在settings.py中添加上述代理中间件配置。
然后,我们需要在middlewares.py中编写代理中间件,用来从代理池中获取IP,并添加到请求中:
import requests
from scrapy import signals
from scrapy.exceptions import NotConfigured
from scrapy.http import HtmlResponse
from fake_useragent import UserAgent
class ProxyPoolMiddleware(object):
proxy_url = 'http://127.0.0.1:5555/random'
def __init__(self):
self.proxy = None
def process_request(self, request, spider):
if self.proxy and self._check_proxy(self.proxy):
request.meta['proxy'] = self.proxy
else:
self.proxy = requests.get(self.proxy_url).text.strip()
request.meta['proxy'] = self.proxy
def process_response(self, request, response, spider):
return response
def process_exception(self, request, exception, spider):
if self.proxy and self._check_proxy(self.proxy):
request.meta['proxy'] = self.proxy
return request
else:
self.proxy = requests.get(self.proxy_url).text.strip()
request.meta['proxy'] = self.proxy
return request
def _check_proxy(self, proxy):
try:
requests.get('https://www.baidu.com/', proxies={'https': 'https://{}'.format(proxy)}, timeout=3)
return True
except:
return False
在这个中间件中,我们定义了一个代理URL(proxy_url),每次发起请求时都会从这个URL获取一个新的代理IP。如果已经有可用的代理IP,则直接使用,否则通过请求获取新的IP,并设置到request.meta['proxy']中。
接下来,我们来创建一个Spider文件(my_spider.py)来爬取目标网站,使用刚刚编写的代理中间件,以下是my_spider.py的代码:
import scrapy
from proxy_example.items import ProxyExampleItem
class MySpider(scrapy.Spider):
name = 'my_spider'
allowed_domains = ['target_site.com']
start_urls = ['https://www.target_site.com/']
def parse(self, response):
# 在这里解析网页内容
pass
在Spider中,我们只关注如何解析目标网站的内容,而不用关心如何获取代理IP。
以上就是使用代理IP池来爬取网站的完整示例,如果需要获取更多代理IP池的使用信息,可以参考文献中提供的相关链接。
示例2:使用隧道代理来爬取网站
使用隧道代理是一种常见的代理方式,它可以让我们通过隧道链接来获取代理IP。以下是如何使用隧道代理来爬取网站的示例:
我们可以使用requests模块来实现一个获取隧道代理的函数:
def get_tunnel_proxy():
proxy_host = 'https://proxyserver.com'
proxy_port = 3128
tunnel_host = 'tunnelserver.com'
tunnel_port = 8080
proxy_type = 'http'
# 构造代理隧道连接
session = requests.Session()
session.proxies = {
'http': 'http://{}:{}/'.format(proxy_host, proxy_port),
'https': 'http://{}:{}/'.format(proxy_host, proxy_port),
}
session.headers.update({'Proxy-Connection': 'Keep-Alive'})
session.get('http://{}'.format(tunnel_host), timeout=10)
# 验证隧道代理
try:
requests.get('http://httpbin.org/ip', proxies={'http': proxy_type + '://{}:{}'.format(tunnel_host, tunnel_port)}, timeout=2)
return '{}://{}:{}'.format(proxy_type, tunnel_host, tunnel_port)
except Exception as e:
print('Error:', e)
return None
在这个函数中,我们通过构造了一个代理隧道连接,并利用获取的IP地址在隧道代理服务器中建立连接来验证代理的有效性,最终返回一个构造好的隧道代理IP(示例中使用的是HTTP代理)。
使用上述方法获取代理IP的过程可以在爬虫启动时进行,例如,我们可以在Spider类中加入相应的过程:
class MySpider(scrapy.Spider):
name = 'my_spider'
allowed_domains = ['target_site.com']
start_urls = ['https://www.target_site.com/']
def start_requests(self):
self.proxy = get_tunnel_proxy() # 获取隧道代理IP
yield scrapy.Request(
self.start_urls[0],
callback=self.parse,
meta={
'proxy': self.proxy,
}
)
def parse(self, response):
# 在这里解析网页内容
pass
在这个Spider中,我们重载了start_requests()函数,通过get_tunnel_proxy()方法获取代理IP,并将其设置到请求的meta中。这样,后续的请求都会通过获取的隧道代理IP来发起连接。
以上就是使用隧道代理来爬取网站的完整示例,更多的代理方式可以参考文献中提供的相关链接。
参考文献
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python爬虫框架scrapy代理中间件掌握学习教程 - Python技术站