解决tls的问题如下博客:
[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED]-优快云博客
但是在此基础上使用代理就不知道怎么办了,urlopen没有proxy的相关参数,查询资料使用opener处理代理之后再使用urlopen或者opener.open
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
使用urllib请求隧道服务器
请求http和https网页均适用
"""
import urllib.request
import ssl
# 全局取消证书验证,避免访问https网页报错
ssl._create_default_https_context = ssl._create_unverified_context
# 隧道域名:端口号
tunnel = "XXX.XXX.com:15818"
# 用户名密码方式
username = "username"
password = "password"
proxies = {
"http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": tunnel},
"https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": tunnel}
}
# 白名单方式(需提前设置白名单)
# proxies = {
# "http": "http://%(proxy)s/" % {"proxy": tunnel},
# "https": "http://%(proxy)s/" % {"proxy": tunnel}
# }
# 要访问的目标网页
target_url = "https://dev.kdlapi.com/testproxy"
# 使用隧道域名发送请求
proxy_support = urllib.request.ProxyHandler(proxies)
opener = urllib.request.build_opener(proxy_support)
# urllib.request.install_opener(opener) 注意此处是全局设置代理,如用这种写法进程内之后的所有urllib请求都会使用代理
# response = urllib.request.urlopen(target_url)
response = opener.open(target_url)
# 获取页面内容
if response.code == 200:
print(response.read().decode('utf-8'))
但是这种方法有个问题,如果使用open则没办法使用ctx的配置解决tsl的版本问题
于是就使用urlopen的context参数来解决,但是新的问题出现了,如果使用context参数则代理记录中没有使用,也就是说没有走代理,如果不带这个参数代理中有记录但是tls版本问题还是解决不了。
经历了漫长的搜索后,终于解决了,直接放代码
import ssl
import urllib3
import base64
from bs4 import BeautifulSoup
# 代理设置
username = ""
password = ""
proxy = ""
# 创建代理 URL
proxy_url = f"http://{proxy}"
# 使用 Base64 编码的凭证
credentials = f"{username}:{password}"
encoded_credentials = base64.b64encode(credentials.encode()).decode()
# 代理头部
proxy_headers = {
'Proxy-Authorization': f'Basic {encoded_credentials}'
}
# 设置 SSL 上下文以允许特定的 TLS 版本
ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
ctx.options |= 0x4 # OP_LEGACY_SERVER_CONNECT
# 创建一个 ProxyManager
http = urllib3.ProxyManager(
proxy_url,
ssl_context=ctx,
proxy_headers=proxy_headers
)
try:
url = ''
# 使用配置好的连接池发送请求
response = http.request('GET', url)
content = response.data.decode('utf-8') # 根据实际网页编码进行调整,这里假设为 utf-8
except urllib3.exceptions.HTTPError as e:
print(f"请求出错: {e}")
except Exception as e:
print(f"其他错误: {e}")
这里有个坑,就是他的代理认证方式和requests包还有其他的那种不一样,他需要把代理链接填入到proxy_url参数,账号和密码填到headers里,我一开始以为这里的url是这种
proxies = { "http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": tunnel}, "https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": tunnel} } 结果一直报代理认证问题,看了看Proxy_PoolManager的源码才改好
这样就可以实现低版本的tls和代理共同起作用了!!