Scrapy 爬虫中的 IP 池:如何使用免费和付费代理 IP 进行反爬虫?
Scrapy 爬虫中可以使用 IP 池来避免反爬虫策略,即使用代理 IP 在请求数据时随机切换 IP,避免被目标网站限制 IP 访问次数过多。本文将介绍如何使用免费和付费代理 IP 实现代理池功能。
一、免费代理 IP 获取及使用
1.1 获取免费代理 IP
可以通过爬取免费代理 IP 网站的方式获取免费代理 IP,例如在 https://www.xicidaili.com/ 中获取免费代理 IP,具体代码如下:
import scrapy class ProxySpider(scrapy.Spider): name = 'proxy' start_urls = ['https://www.xicidaili.com/'] def parse(self, response): proxies = response.xpath('//tr[@class="odd" or @class=""]') for proxy in proxies: ip = proxy.xpath('td[2]/text()').extract_first() port = proxy.xpath('td[3]/text()').extract_first() yield {'proxy': f'{ip}:{port}'}
1.2 使用免费代理 IP
在 Scrapy 中使用代理 IP 可以使用 Request
的 meta
参数将代理 IP 加入请求头中。需要把免费代理 IP 存储到列表或队列中,以便取出其中的某个代理 IP,同时建议对于不可用的代理 IP 进行删除操作。具体代码如下:
class MySpider(scrapy.Spider): def __init__(self, *args, **kwargs): super(MySpider, self).__init__(*args, **kwargs) self.proxies = [] def start_requests(self): url = 'https://pidancode.com' for i in range(10): yield scrapy.Request(url, callback=self.parse, meta={'proxy': self.get_random_proxy()}) def parse(self, response): # parse response def get_random_proxy(self): if len(self.proxies) == 0: self.proxies = self.get_proxies_from_database() # 从数据库中获取代理 IP 列表 proxy = random.choice(self.proxies) del self.proxies[self.proxies.index(proxy)] return proxy
二、付费代理 IP 获取及使用
2.1 获取付费代理 IP
可以在代理 IP 资源网站上购买付费代理 IP,例如在 https://www.kuaidaili.com/ 中购买付费代理 IP,具体代码如下:
import scrapy class ProxySpider(scrapy.Spider): name = 'proxy' start_urls = ['https://www.kuaidaili.com/ops/'] def parse(self, response): urls = response.css('.page-content .con .table tr td:nth-child(1) a::attr(href)').extract() for url in urls: yield scrapy.Request(url, callback=self.parse_proxy) def parse_proxy(self, response): proxies = response.css('.con table tbody tr') for proxy in proxies: ip = proxy.css('td:nth-child(1)::text').extract_first() port = proxy.css('td:nth-child(2)::text').extract_first() yield {'proxy': f'{ip}:{port}'}
2.2 使用付费代理 IP
使用付费代理 IP 和使用免费代理 IP 类似,只需要在请求时把代理 IP 加入请求头中即可。不同之处在于,付费代理 IP 是具有时限的,需要根据使用时间进行续费或重新购买。具体代码如下:
class MySpider(scrapy.Spider): def __init__(self, *args, **kwargs): super(MySpider, self).__init__(*args, **kwargs) self.proxies = [] self.proxy_auth = '' def start_requests(self): url = 'https://pidancode.com' for i in range(10): yield scrapy.Request(url, callback=self.parse, meta={'proxy': self.get_random_proxy(), 'proxy_auth': self.proxy_auth}) def parse(self, response): # parse response def get_random_proxy(self): if len(self.proxies) == 0: self.proxies = self.get_proxies_from_api() # 从 API 中获取代理 IP 列表 proxy = random.choice(self.proxies) del self.proxies[self.proxies.index(proxy)] return proxy
需要注意的是,在使用付费代理 IP 时,有些代理 IP 需要进行身份认证,需要在请求头中加入身份认证信息。具体信息可以在代理 IP 资源网站获取。例如,
self.proxy_auth = 'Basic ' + base64.b64encode(b'username:password').decode('utf-8')
三、IP 池维护
在使用 IP 池时,需要对 IP 进行动态维护,去除不可用的 IP。可以在请求失败时对代理 IP 逐一判断并去除不可用的代理 IP。具体代码如下:
class MySpider(scrapy.Spider): def __init__(self, *args, **kwargs): super(MySpider, self).__init__(*args, **kwargs) self.proxies = [] self.proxy_auth = '' def start_requests(self): url = 'https://pidancode.com' for i in range(10): yield scrapy.Request(url, callback=self.parse, meta={'proxy': self.get_random_proxy(), 'proxy_auth': self.proxy_auth}) def parse(self, response): if response.status == 200: # parse response pass else: self.remove_proxy(response.meta['proxy']) def remove_proxy(self, proxy): if proxy in self.proxies: self.proxies.remove(proxy) # save to database def get_random_proxy(self): if len(self.proxies) == 0: self.proxies = self.get_proxies_from_api() # 从 API 中获取代理 IP 列表 proxy = random.choice(self.proxies) return proxy
四、总结
本文介绍了如何在 Scrapy 爬虫中使用代理 IP 来避免反爬虫策略,包括免费和付费代理 IP 的获取及使用,以及 IP 池的维护。需要注意的是,在使用代理 IP 时,需要考虑代理 IP 的稳定性和可用性,避免因使用不稳定的代理 IP 而导致爬虫失败。
相关文章