Python3 通过使用 SOCKS5H 来解决爬虫 SSL 错误和境内 DNS 污染的问题

如果你急于解决爬虫 HTTP 代理池访问 HTPPS 出错,并且自己有境外服务器的话,我直接给出解决方案:服务器搭建 SOCKS5 代理并在代码中以 socks5h://账号:密码@IP:端口 的格式使用
以 Python3 为例:

proxy = {
    "http": "socks5h://username123:[email protected]:13233",
    "https": "socks5h://username123:[email protected]:13233"
}
response = requests.get(url,proxies=proxy,verify=False)
print(response.content)

注意: 代理的协议选择要使用 SOCKS5H,下面我会放使用 HTTP 和 SOCKS5 产生的错误供参考。

1、使用 HTTP 代理时

url = "https://steamcommunity.com/market/priceoverview/?appid=730&currency=1&market_hash_name=Clutch%20Case"
proxy = {
    "http": "http://128.129.139.201:13233",
    "https": "http://128.129.139.201:13233"
}
response = requests.get(url,proxies=proxy,verify=False)
print(response.content)

requests.exceptions.ProxyError: HTTPSConnectionPool(host=‘steamcommunity.com’, port=443): Max retries exceeded with url: /market/priceoverview/?appid=730&currency=1&market_hash_name=Clutch%20Case (Caused by ProxyError(‘Cannot connect to proxy.’, ConnectionResetError(10054, ‘远程主机强迫关闭了一个现有的连接。’, None, 10054, None)))

2、使用 HTTPS 代理时

url = "https://steamcommunity.com/market/priceoverview/?appid=730&currency=1&market_hash_name=Clutch%20Case"
proxy = {
    "http": "http://128.129.139.201:13233",
    "https": "https://128.129.139.201:13233"
}
response = requests.get(url,proxies=proxy,verify=False)
print(response.content)

requests.exceptions.ProxyError: HTTPSConnectionPool(host=‘steamcommunity.com’, port=443): Max retries exceeded with url: /market/priceoverview/?appid=730&currency=1&market_hash_name=Clutch%20Case (Caused by ProxyError(‘Cannot connect to proxy.’, ConnectionResetError(10054, ‘远程主机强迫关闭了一个现有的连接。’, None, 10054, None)))

3、使用 SOCKS5 代理时

url = "https://steamcommunity.com/market/priceoverview/?appid=730&currency=1&market_hash_name=Clutch%20Case"
proxy = {
    "http": "socks5://128.129.139.201:13233",
    "https": "socks5://128.129.139.201:13233"
}
response = requests.get(url,proxies=proxy,verify=False)
print(response.content)

socks.GeneralProxyError: Socket error: 0x05: Connection refused
requests.exceptions.ConnectionError: SOCKSHTTPSConnectionPool(host=‘steamcommunity.com’, port=443): Max retries exceeded with url: /market/priceoverview/?appid=730&currency=1&market_hash_name=Clutch%20Case (Caused by NewConnectionError('<urllib3.contrib.socks.SOCKSHTTPSConnection object at 0x03C29450>: Failed to establish a new connection: 0x05: Connection refused'))

4、最后使用 SOCKS5 代理,但是协议处变为 SOCKS5H

url = "https://steamcommunity.com/market/priceoverview/?appid=730&currency=1&market_hash_name=Clutch%20Cahhse"
proxy = {
    "http": "socks5h://128.129.139.201:13233",
    "https": "socks5h://128.129.139.201:13233"
}
response = requests.get(url,proxies=proxy,verify=False)
print(response.content)

proxy 200 b'{“success”:true,“lowest_price”:"$0.18",“volume”:“210,212”,“median_price”:"$0.18"}'

返回了我需要的数据,成功。


在处理这个问题的时候,感觉把学的网络全还给了老师。
HTTP 属于应用层,而 SOCKS5 属于会话层,这就意味着 SOCKS5 所能代理的范围会比 HTTP 协议更广。
而 SOCKS5H 与 SOCKS5 的区别则是:SOCKS5 在本地解析 Hostname,而 SOCKS5H 则有 SOCKS5 代理所部署的服务器解析 Hostname。
换句话说,SOCKS5 适合本地能够解析目标主机域名(比如 GitHub)但是访问速度慢的域名来提高下载速度,而 SOCKS5H 则可以用来代理本地不能解析的网站(比如 Google),由服务器解析目标主机域名。

顺便附上服务端代理的搭建脚本:
HTTP 代理:CentOS7 下一键安装 Tinyproxy 代理
SOCKS5 代理:CentOS7 下一键安装 SOCKS5 代理
同时安装 HTTP 和 SOCKS5 代理:CentOS7 下一键安装 GOST 并启动 HTTP 和 SOCKS5 代理服务

结束。