python 爬虫如何设置代理 ip 使用教程

用Python写爬虫,代理IP的设置方式由选用的库决定。requests、urllib、aiohttp、Scrapy写法各不相同,但底层逻辑一致:把网络请求出口从本机IP替换成代理服务器IP。先从requests说起,大部分人入门爬虫都会优先使用这个库。

requests依靠proxies参数配置代理,接收字典类型,键代表协议,值填写代理地址。示例代码:


import requests

proxies = { "http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080", }

python 爬虫如何设置代理 ip 使用教程

resp = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=10) print(resp.json())

代理需要账号密码认证,直接把认证信息写进URL:http://user:pass@127.0.0.1:8080。密码包含特殊字符时,要先做URL编码,否则解析报错。也可以使用requests.auth.HTTPProxyAuth,不过proxies参数不方便挂载auth对象,大部分开发者直接选择URL内嵌认证。

只单独配置http或者https代理,会出现遗漏。比如只填写http代理,访问https站点,requests可能不会走代理。稳妥做法是两个协议都配置,地址保持相同。

代理连接失败或者超时,requests抛出ProxyError或者ConnectTimeout。爬虫代码不能因为单个失效代理直接终止任务,用try捕获异常,请求失败就切换下一个代理。

urllib写起来比requests繁琐,依靠ProxyHandler和build_opener实现代理:


from urllib.request import ProxyHandler, build_opener, Request

proxy = ProxyHandler({ "http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080", }) opener = build_opener(proxy) req = Request("https://httpbin.org/ip") resp = opener.open(req, timeout=10) print(resp.read().decode())

urllib的代理认证同样可以在URL写入user:pass@host:port,或者搭配HTTPPasswordMgrWithDefaultRealm、ProxyBasicAuthHandler,但后者代码冗长,日常开发直接用URL内嵌方式足够。

aiohttp多用于异步爬虫,代理设置比较直接:


import aiohttp import asyncio

async def fetch(): async with aiohttp.ClientSession() as session: async with session.get( "https://httpbin.org/ip", proxy="http://127.0.0.1:8080", timeout=aiohttp.ClientTimeout(total=10) ) as resp: print(await resp.json())

asyncio.run(fetch())

aiohttp代理认证写在URL内。如果使用SOCKS5代理,需要额外安装aiohttp-socks,借助ProxyConnector,不能直接传入proxy参数。

Scrapy配置方式略有区别。默认HttpProxyMiddleware读取环境变量http_proxy和https_proxy,更常用的方式是在settings.py启用中间件,通过request.meta['proxy']单独为每一条请求指定代理:


DOWNLOADER_MIDDLEWARES = { 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 110, }

spider内代码:


def start_requests(self): for url in self.start_urls: yield scrapy.Request( url, meta={"proxy": "http://127.0.0.1:8080"}, callback=self.parse )

代理需要账号密码,Scrapy支持在proxy URL写入user:pass@host:port。部分Scrapy版本对认证代理支持不佳,可以使用第三方中间件scrapy-proxies,自动从代理列表随机选取,支持账号认证,配置简单。

代理IP来源方面,网上免费代理资源很多,但可用率很低。从GitHub拉取代理列表,几百条IP里能正常使用的寥寥无几,存活时间很短。免费代理只适合测试,正式跑爬虫任务,付费代理或者自建代理稳定性更好。付费代理按流量或者IP数量计费,品质参差不齐,购买前先用测试额度测试延迟和成功率。

拿到代理之后第一件事就是验证。最简单的方式,用代理访问httpbin.org/ip,查看返回的origin是否为代理IP。如果返回本机IP,代表代理没有生效,或是透明代理。透明代理会暴露真实本机IP,等同于没有更换IP。匿名代理至少隐藏本机IP,高匿代理不会携带Via请求头。

批量校验代理可以用多线程或者异步,不要逐个串行测试。简易检测脚本:


import requests from concurrent.futures import ThreadPoolExecutor

def check(proxy): try: r = requests.get( "https://httpbin.org/ip", proxies={"http": proxy, "https": proxy}, timeout=5 ) if r.status_code == 200: return proxy, r.json()["origin"] except Exception: pass return proxy, None

proxies = ["http://1.2.3.4:8080", "http://5.6.7.8:8080"] with ThreadPoolExecutor(max_workers=20) as pool: for proxy, ip in pool.map(check, proxies): if ip: print(f"{proxy} -> {ip}")

爬虫任务规模扩大之后,就需要搭建代理池。最简单方案维护代理列表,每次请求随机挑选,请求失败就更换。进阶方案用Redis存储代理,后台定时任务每隔几分钟检测全部代理有效性,剔除失效IP,保留可用代理。爬虫从Redis随机获取代理,使用完毕放回池内,有效提升代理可用率。

代理池代码逻辑不算复杂,核心两个函数:抓取代理、验证代理。抓取可以从免费代理站点或者付费代理API拉取数据,验证就是上面的check函数。校验通过的代理存入Redis集合,爬虫使用SRANDMEMBER随机取出。取出的代理请求失败,直接从集合删除,重新获取新代理。

SOCKS代理和HTTP代理写法不一样。requests使用SOCKS需要先安装requests[socks],proxies配置如下:


proxies = { "http": "socks5://127.0.0.1:1080", "https": "socks5://127.0.0.1:1080", }

SOCKS5支持UDP、TCP,底层能力比HTTP代理更强,但速度有时不如HTTP代理。aiohttp使用SOCKS依赖aiohttp-socks,Scrapy需要scrapy-socks中间件,都不是原生支持,需要额外安装依赖。

有不少坑需要留意。HTTPS代理采用CONNECT方法,不是普通GET请求。部分代理只支持HTTP,访问HTTPS网站会直接报错。不同代理IP响应速度差距很大,同一个IP不同时段延迟波动明显,代理池要定期刷新。并发过高,代理服务器负载压力大,要控制并发数量,避免打垮代理服务。另外爬虫使用代理,需要遵守目标网站robots.txt以及当地法律法规,不要用来开展违规操作。

代理没有一劳永逸的方案。免费代理需要频繁更换,付费代理要仔细挑选服务商,自建代理成本高但可控。先从requests的proxies参数上手,把代理校验、轮换逻辑调试通,再迁移到Scrapy或者异步爬虫,慢慢积累实操经验。

免责声明:本文提供的方法与建议仅供技术参考,实际部署效果受机房环境、运营商线路、系统配置等多重因素影响。请在专业人员指导下操作,因自行操作导致的业务损失本站不承担责任。

相关推荐