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

转载:

为什么你的隧道代理没有更换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机制能够放慢你的申请,须要您依据业务理论状况进行判断。

更多爬虫技术好文

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理