爬虫-HTTP代理

前言:在进行爬虫操作时,因为待爬系统后端会进行限流操作,所以使用一个ip不断进行请求会造成ip被封,为针对这种反爬手段我们可以进行ip代理的方式。
如何获取代理服务器?
可以购买云服务器(亚马逊或者阿里云服务器)但自行搭建代理服务器的成本较高(可靠,可控),我们也可以通过google或者baidu找到一些免费服务器的网站:
http://proxy-list.org
http://free-proxy-list.net
http://www.xicidaili.com
…等
操作步骤(以Scrapy框架为例):
1: 先创建项目

scrapy startproject xici_proxy

2:创建spider文件(在xici_proxy目录下)

scrapy genspider xici "www.xicidaili.com"

3:在配置文件setting.py文件设置请求头

USER_AGENT = 'User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0'

4:实现spider爬取代理服务器信息,并过滤掉不可用的代理

# -*- coding: utf-8 -*-
import scrapy
from scrapy import Request
import json

class XiciSpider(scrapy.Spider):
    name = 'xici'
    allowed_domains = ['www.xicidaili.com']

    def start_requests(self):
        for i in range(1, 4):
            yield Request("http://www.xicidaili.com/nn/%s" % i)

    def parse(self, response):
        for sel in response.xpath("//table[@id='ip_list']/tr[position()>1]"):
            # 提取代理的ip, port, http/https
            ip = sel.css("td:nth-child(2)::text").extract_first()
            port = sel.css("td:nth-child(3)::text").extract_first()
            scheme = sel.css("td:nth-child(6)::text").extract_first().lower()
            # 使用爬虫得到得到的代理去发送请求,验证代理是否可用
            url = "%s://httpbin.org/ip" % scheme
            proxy = "%s://%s:%s" % (scheme, ip, port)
            meta = {
                "proxy": proxy,
                "dont_retry": True,
                "download_timeout": 10,
                # 以下两个字段是传给check_available方法的信息,方便检测
                "_proxy_scheme": scheme,
                "_proxy_ip": ip
            }
            yield Request(url, callback=self.check_availabel, meta=meta, dont_filter=True)

    def check_availabel(self, response):
            proxy_ip = response.meta["_proxy_ip"]
            # 判断代理是否具有隐藏IP的功能
            if proxy_ip == json.loads(response.text)["origin"]:
                yield {
                    "proxy_scheme": response.meta["_proxy_scheme"],
                    "proxy": response.meta["proxy"]
                }

5:执行spider并生成相应的json文件

scrapy crawl xici.py -o proxy_list.join

实现随机代理(Scrapy框架)
基于HttpProxyMiddleware实现一个随机代理下载中间件
1:在middlewares.py中实现RandomHttpProxyMiddleware

from scrapy.downloadermiddlewares.httpproxy import HttpProxyMiddleware
from collections import defaultdict
import json
import random

class RandomHttpProxyMiddleware(HttpProxyMiddleware):
    
    def __init__(self, auth_encoding="latin-1", proxy_file=None):
        if not proxy_file:
            raise FileNotFoundError
        self.auth_encoding = auth_encoding
        # 两个列表维护HTTP和HTTPS
        self.proxies = defaultdict(list)
        # 从json文件读取代理服务器信息
        with open(proxy_file) as f:
            proxy_list = json.load(f)
            for proxy in proxy_list:
                scheme = proxy["proxy_scheme"]
                url = proxy["proxy"]
                self.proxies[scheme].append(self._get_proxy(url, scheme))
    
    @staticmethod
    def from_crawler(cls, crawler):
        # 从配置文件中读取用户验证信息的编码
        auth_encoding = crawler.settings.get("HTTPPROXY_AUTH_ENCODING","latin-1")
        # 从配置文件中读取代理服务器列表文件
        proxy_file = crawler.settings.get("HTTPPROXY_PROXY_LIST_FILE")
        return cls(auth_encoding, proxy_file)

    def _set_proxy(self, request, scheme):
        # 随机选择一个代理
        creds, proxy = random.choice(self.proxies[scheme])
        request.meta["proxy"] = proxy
        if creds:
            request.headers["Proxy-Authorization"] = b"Basic" + creds

代码解释:
1:仿照HttpProxyMiddleware构造器实现RandomHttpProxyMiddleware构造器,首先从代理服务器列表文件(配置文件中)读取代理服务器信息,然后将他们按协议分别存入不同的列表,由self.proxis字典维护.:
2:_set_proxy方法负责对每一个request请求设置代理,重写_set_proxy。对每一个request,根据请求协议获取self.proxis中的代理服务器列表,然后从中随机抽取一个代理。赋值给request.meta[“proxy”]。

2: 在配置文件setting.py中启用RandomHttpProxyMiddleware,并指定所要使用的代理服务器列表(json文件)

DOWNLOADER_MIDDLEWARES = {
   'xici_proxy.middlewares.RandomHttpProxyMiddleware': 700,
}
# 前面获取的服务器信息json文件
HTTPPROXY_PROXY_LIST_FILE = "proxy_list.json"

3: 可以编写一个spider进行测试刚写的中间件

# -*- coding: utf-8 -*-
import scrapy
from scrapy import Request
import json

class TestSpider(scrapy.Spider):
    name = "test_spider"
    
    def start_requests(self):
        for _ in range(100):
            yield Request("http://httpbin.org/ip", dont_filter=True)
            yield Request("http://httpbin.org/ip", dont_filter=True)
    
    def parse(self, response):
        print(json.loads(response.text))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Enougme

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值