使用requests-html结合Tor匿名爬取遇SOCKS5Error问题求助
解决SOCKS5代理错误+实现匿名爬取/IP切换方案
嘿,我来帮你搞定这个socks.SOCKS5Error: 0x01: General SOCKS server failure的问题,同时实现你需要的匿名爬取和指定请求次数后切换IP的功能。
一、先排查代理报错的核心原因
这个错误基本和代理服务本身或配置有关,先从这几点入手:
- 你用的9150端口是Tor Browser的默认SOCKS5端口,务必确保Tor Browser已经启动并正常运行——如果Tor没开,代理肯定连不上
- 确认
127.0.0.1:9150确实是当前Tor的监听端口(可以在Tor的设置里查看网络选项) - 先用普通
requests库测试代理是否可用,排除requests-html的问题:
import requests proxies = { 'http': 'socks5://127.0.0.1:9150', 'https': 'socks5://127.0.0.1:9150' } try: r = requests.get('http://icanhazip.com', proxies=proxies) print(r.text.strip()) except Exception as e: print(f"代理测试失败:{e}")
如果这个测试都失败,先把Tor服务调通;如果测试成功,再看requests-html的配置问题。
二、requests-html正确配置SOCKS5代理的姿势
你之前用全局替换socket.socket = socks.socksocket的方式,容易和requests-html的底层实现冲突。更稳妥的是给HTMLSession单独配置代理:
from requests_html import HTMLSession from requests.adapters import HTTPAdapter import socks import socket # 定义创建SOCKS5代理socket的函数 def create_socks5_socket(): sock = socks.socksocket() sock.set_proxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', 9150) return sock # 初始化HTMLSession session = HTMLSession() # 给HTTP和HTTPS适配器替换成带代理的socket for protocol in ['http://', 'https://']: adapter = HTTPAdapter() adapter.init_poolmanager( socket_options=[(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)], socket_factory=create_socks5_socket ) session.mount(protocol, adapter) # 测试请求 try: r = session.get('http://icanhazip.com') print(f"当前代理IP:{r.text.strip()}") # 后续正常使用r.html解析内容,比如r.html.find('xxx') except socks.SOCKS5Error as e: print(f"SOCKS5代理错误:{e}") except Exception as e: print(f"请求出错:{e}")
三、实现指定次数请求后切换IP
如果用Tor的话,我们可以通过发送信号让Tor切换IP;如果用第三方代理池,直接替换代理地址即可。这里以Tor为例:
import os import signal import time def switch_tor_ip(): # Linux/macOS系统:给Tor进程发送SIGHUP信号切换IP # Windows系统请替换成对应的Tor进程管理命令(比如用taskkill重启Tor) try: pid = os.popen("pgrep tor").read().strip() if pid: os.kill(int(pid), signal.SIGHUP) print("✅ 已切换Tor IP") time.sleep(5) # 等待Tor重新建立连接 else: print("❌ 未找到Tor进程,请确保Tor Browser已启动") except Exception as e: print(f"切换IP失败:{e}") # 示例:每3次请求切换一次IP request_count = 0 max_requests_per_ip = 3 while request_count < 10: try: r = session.get('http://icanhazip.com') print(f"请求次数:{request_count+1},当前IP:{r.text.strip()}") request_count += 1 # 达到指定次数时切换IP if request_count % max_requests_per_ip == 0: switch_tor_ip() except Exception as e: print(f"请求失败:{e}") # 请求失败时也切换IP,避免死在同一个代理上 switch_tor_ip()
额外小贴士
- 爬取时记得添加真实的
User-Agent等请求头,模拟浏览器行为:headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' } r = session.get('http://icanhazip.com', headers=headers) - 可以给session添加重试机制,应对临时的代理故障:
from urllib3.util.retry import Retry retry_strategy = Retry( total=3, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504] ) adapter = HTTPAdapter(max_retries=retry_strategy) session.mount('http://', adapter) session.mount('https://', adapter)
内容的提问来源于stack exchange,提问作者leaf
相关产品推荐
相关产品推荐

