urllib自定义opener对象设置代理IP

urllib.request.urlopen()源代码——urlopen()在干什么

返回opener.open(url, data, timeout)方法的结果
  _opener = None  # _opener被赋值为None
def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
            *, cafile=None, capath=None, cadefault=False, context=None):
    global _opener
    if cafile or capath or cadefault:
        import warnings
        warnings.warn("cafile, capath and cadefault are deprecated, use a "
                      "custom context instead.", DeprecationWarning, 2)
        if context is not None:
            raise ValueError(
                "You can't pass both context and any of cafile, capath, and "
                "cadefault"
            )
        if not _have_ssl:
            raise ValueError('SSL support not available')
        context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH,
                                             cafile=cafile,
                                             capath=capath)
        # send ALPN extension to indicate HTTP/1.1 protocol
        context.set_alpn_protocols(['http/1.1'])
        https_handler = HTTPSHandler(context=context)
        opener = build_opener(https_handler)
    elif context:
        https_handler = HTTPSHandler(context=context)
        opener = build_opener(https_handler)
    elif _opener is None:  # 默认情况下会调用build_opener()
        _opener = opener = build_opener()
    else:
        opener = _opener
    return opener.open(url, data, timeout)

urllib.request.build_opener()

build_opener()函数返回的是OpenerDirector类的实例
 def build_opener(*handlers):
    opener = OpenerDirector()  # 创建OpenerDirector类的实例opener
    default_classes = [ProxyHandler, UnknownHandler, HTTPHandler,
                       HTTPDefaultErrorHandler, HTTPRedirectHandler,
                       FTPHandler, FileHandler, HTTPErrorProcessor,
                       DataHandler]
    if hasattr(http.client, "HTTPSConnection"):
        default_classes.append(HTTPSHandler)
    skip = set()
    for klass in default_classes:
        for check in handlers:
            if isinstance(check, type):
                if issubclass(check, klass):
                    skip.add(klass)
            elif isinstance(check, klass):
                skip.add(klass)
    for klass in skip:
        default_classes.remove(klass)

    for klass in default_classes:
        opener.add_handler(klass())

    for h in handlers:
        if isinstance(h, type):
            h = h()
        opener.add_handler(h)
    return opener  # 返回实例opener

urllib.request.OpenerDirector().open()

Class OpenerDirectorOpenerDirector为一个类。由上面的代码opener = build_opener()得,opener为OpenerDirector类的一个实例即根据OpenerDirector类创建的对象(build_opener()将创建的实例赋值给opener)。

所以urlopen返回的结果是opener.open()方法的结果——响应(response),而opener.open()是一个更底层的方法,它允许自定义opener对象发送特定的请求,获取响应结果。

自定义opener对象发送请求(添加网络代理Proxy)

使用代理服务器时,网络请求会先发送到代理服务器,然后由代理服务器转发到目标服务器。这个过程中目标服务器看到的将是代理服务器的IP地址,而不是原始IP。代理IP作为中介,隐藏了实际的IP。设置代理IP能:

  1. 隐私保护,隐藏实际IP地址,从而保护网络身份和位置信息。
  2. 绕过限制,某些网站或服务可能基于IP地址实施地址限制或访问控制。通过代理IP能访问通常无法访问的资源。
  3. 负载均衡和缓存,将请求发送到不同服务器,以及缓存内容以加快访问速度。
  4. 代理IP被反爬虫程序识别被封,不影响原IP。

在build_opener()函数的参数中添加一个或多个处理程序(handlers)

from urllib.request import Request, ProxyHandler, build_opener
# 设置访问地址
url = 'http://httpbin/get'
# 设置请求对象
req = Request(url)
# 构建可以使用代理的服务器
# ProxyHandler({'type': 'ip: port'})
handler = ProxyHandler({'http': '123.126.158.50: 80'})  # 站大爷免费ip(免费ip容易挂,可以多次尝试)
# 构建一个opener对象
opener = build_opener(handler)
# 发送请求
resp = opener.open(req)
# 打印结果
print(resp.read().decode())

使用代理的运行结果

{
  "args": {}, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Host": "httpbin.org", 
    "User-Agent": "Python-urllib/3.12", 
    "X-Amzn-Trace-Id": "Root=1-66e7f898-0a1040c7382170613a7c9dff"
  }, 
  "origin": "123.126.158.50", 
  "url": "http://httpbin.org/get"
}

使用OpenerDirector类的add_handler()方法

from urllib.request import build_opener, ProxyHandler
# 请求地址
url = 'http://httpbin.org/get'
# 构建可以使用代理的控制器
handler = ProxyHandler({'http': '111.26.177.28: 9091'})
# 构建默认的opener对象
opener = build_handler()
# 使用add_handler方法添加处理器
opener.add_handler(handler)
# 发送请求
resp = opener.open(url)
# 打印结果
print(resp.read().decode())
不使用代理的运行结果
 {
  "args": {}, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Host": "httpbin.org", 
    "User-Agent": "Python-urllib/3.12", 
    "X-Amzn-Trace-Id": "Root=1-66e7f9ea-18ae78a77b2131803bd2f0cd"
  }, 
  "origin": "111.8.72.145", 
  "url": "http://httpbin.org/get"
}

代理分类

  • 透明代理: 目标网站知道你使用了代理并且知道你的源IP地址。
  • 匿名代理: 匿名程度比较低,也就是网站知道你使用了代理,但是并不知道你的源IP地址。
  • 高匿代理: 目标网站即不知道你使用了代理,也不知道源IP。

代理网站

小象代理

快代理

云代理

66ip代理

站大爷:https://www.zdaye.com/free/

开心代理

讯代理

posted @ 2024-09-16 15:57  松鼠q  阅读(4)  评论(0编辑  收藏  举报