关于python爬虫:为什么隧道代理没有更换IP

8次阅读

共计 2627 个字符,预计需要花费 7 分钟才能阅读完成。

转载:

为什么你的隧道代理没有更换 IP

有局部小伙伴反馈在客户端应用隧道代理动静版(每次申请更换 IP)的过程中发现没有更换 IP,遂狐疑是咱们隧道代理服务器的问题,其实不然。明天咱们就在这里谈谈,为什么会有隧道代理会呈现没有更换 IP 的状况。

长久连贯

须要理解,HTTP/1.1(以及 HTTP/1.0 的各种加强版本)容许 HTTP 在申请解决完结之后将 TCP 连贯放弃在关上状态(并不会立刻敞开),以便为将来的 HTTP 申请重用之前建设的连贯。
在申请解决完结之后依然放弃在关上状态的 TCP 连贯被称为长久连贯。而非长久连贯则会在每个申请完结之后敞开。长久连贯会在不同申请之间放弃关上状态,直到客户端或服务端决定将其敞开为止。
重用已对指标服务器关上的闲暇长久连贯,就能够避开迟缓的连贯建设阶段。而且,曾经关上的连贯还能够防止慢启动的拥塞适应阶段,以便更疾速地进行数据的传输。

HTTP 客户端举例

通过下面的内容咱们理解到,开启 Keep-Alive 能够更疾速的进行数据传输。
最常见的应用场景就是浏览器在关上一个网页,并不会为了每个资源都开打一个 TCP 连贯,而是会同时关上大量 TCP 连贯,利用 Keep-Alive 机制,一直利用大量连贯传输少数 HTTP 申请。
因为去除了进行连贯和敞开连贯的开销,因而放慢访问速度。

在一些编程语言开发的 HTTP 客户端,爬虫框架中,除了会应用异步形式发送申请,也会应用 TCP 连贯复用来减速解决使用者的申请。

Python-Requests

应用 Requests 提供的 Session 发送申请时,除了会主动保留 cookie,还会应用 urllib3 底层提供的 connection-pooling(连接池)

例如利用 requests-session 配置隧道代理动静版间断发送 3 个申请并打印出以后应用的代理 IP

import time
import requests
 
 
username = "txxxxxxxxxxxxx"
password = "password"
tunnel = "tpsXXX.kdlapi.com"
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}
}
s = requests.session()
for i in range(3):
    res = s.get('https://dev.kdlapi.com/testproxy', proxies=proxies)
    print(res.text)
    time.sleep(1)
sucess! client ip: 175.7.196.238 
sucess! client ip: 175.7.196.238 
sucess! client ip: 175.7.196.238 

能够发现三次都是同一个 IP,并且应用 Wireshark 抓包查看,很显著这三次申请都走了一个 TCP 连贯。

Python-Scrapy

Scrapy 底层采纳的 Twisted 异步网络编程框架,在 Twisted 源码中就能找到对于连贯复用的实现
twisted/web/_newclient.py
Class HTTP11ClientProtocol
_finishResponse_WAITING()

•拿到指标网站响应后,在_finishResponse_WAITING 函数中判断响应 header 中的 connection 是否为 close•如果为 close 调用 self._giveUp(),间接敞开本次连贯•否则调用 self.transport.resumeProducing(),持续重用这条 TCP 连贯,读取响应或者发送 HTTP 申请。

起因

因为隧道代理动静版底层的实现是只有在新建设连贯的状况下,能力将申请转发给不同的代理服务器。如果应用代理的 HTTP 客户端在拿到响应后并没有间接敞开 TCP 连贯,后续的 HTTP 申请可能会持续在这条 TCP 连贯上发送,导致多个 HTTP 申请应用的是雷同的代理 IP。

解决办法

那如何在申请完结后被动敞开连贯呢?
在 HTTP/1.0 中,keep-alive 并 不 是 默 认 使 用 的。客 户 端 必 须 发 送 一 个 Connection: Keep-Alive 申请首部来激活 keep-alive 连贯。
而在 HTTP/1.1 中默认启用 Keep-Alive,默认状况下所在 HTTP1.1 中所有连贯都被放弃,除非在申请头或响应头中指明要在响应完结后敞开连贯:Connection: Close。
通常来说,只须要在申请头中退出 Connection: Close,指标服务器辨认后,在响应头中也会退出 Connection: Close,并且在发送完响应后被动敞开连贯。
所以如果你不能确定你所应用的 HTTP 客户端是否会在申请完结后敞开申请,是能够在发送申请的 header 中被动加上:Connection: Close

仍旧是上述 Python-Requests 代码

headers = {"Connection": "close"}
s = requests.session()
for i in range(3):
    res = s.get('https://dev.kdlapi.com/testproxy', proxies=proxies, headers=headers)
    print(res.text)
    time.sleep(1)
sucess! client ip: 121.205.214.213 
sucess! client ip: 27.148.203.221 
sucess! client ip: 114.99.131.98 

每次申请都更换了 IP,再次查看 Wireshark 抓包数据,三次 HTTP 申请,每次都建设了新的 TCP 连贯。

总结

应用隧道代理动静版发现没有更换 IP 很有可能是 HTTP 客户端复用了之前建设的 TCP 连贯,由此来放慢网络申请。
大家购买隧道带动静版就是为了每次申请更换 IP,复用了之前的 TCP 连贯就无奈达到更换 IP 的成果,只须要在申请头中退出 Connection: Close,显式地指出本次连贯传输实现就立刻敞开即可。
当然,如果您不须要每次申请都切换 IP,应用 keep_alive 机制能够放慢你的申请,须要您依据业务理论状况进行判断。

更多爬虫技术好文

正文完
 0