前言:在进行爬虫操作时,因为待爬系统后端会进行限流操作,所以使用一个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))