Scrapy 爬虫中的 IP 池:如何使用免费和付费代理 IP 进行反爬虫?

2023-04-17 00:00:00 付费 爬虫 如何使用

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 可以使用 Requestmeta 参数将代理 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 而导致爬虫失败。

相关文章