前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[1277]使用隧道代理保持IP临时不变和切换IP

[1277]使用隧道代理保持IP临时不变和切换IP

作者头像
周小董
发布2024-05-02 08:02:39
980
发布2024-05-02 08:02:39
举报
文章被收录于专栏:python前行者python前行者

使用隧道转发爬虫代理保持IP/切换IP

隧道转发代理: 简单来说每秒新建http请求,每个http请求随机分配一个代理IP,每个IP有效时间20秒。毕竟是随机分配的,每个http请求分配的代理IP都不一样,那如何保持每个http请求是同一个IP?

采用Proxy-Tunnel自主切换IP: 该模式适合一些需要登陆、Cookie缓存处理等爬虫需要精确控制IP切换时机的业务。 爬虫程序可以通过设置HTTP头Proxy-Tunnel: 随机数, 当随机数相同时,访问目标网站的代理IP相同。

例如 :需要登录,获取数据两个请求在一个IP下,只需对这组请求设置相同Proxy-Tunnel,例如:Proxy-Tunnel: 12345, 该组请求在代理有效期内使用相同的代理IP。

注意 :同一时间不同请求组可以设置不同Proxy-Tunnel: 随机数,并发完成数据爬取。

使用相同IP访问HTTPS目标网站: 1、使用Connection: keep-aliveProxy-Connection: keep-alive方式访问目标网站,代理会确保在一个会话中的所有请求都通过一个IP到达目标网站。通过设置Proxy-Connection: Keep-AliveConnection: Keep-Alive可以保持同一个Session代理IP不变。

2、设置相同Proxy-Tunnel,有些库封装比较高层次,请务必确认向代理发送了该HTTP头。

例如:需要登录,获取数据两个请求在一个IP下,只需保证该组请求在一个T秒(Keep-Alive)会话下, 该组请求在代理有效期内使用相同的代理IP。

HTTPS 使用爬虫代理访问HTTPS网站时,会自动开启KeepAlive,同一个Session(HTTPS会话)代理IP不变。如需要每个请求强制切换IP,可以设置Proxy-Connection: CloseConnection: Close

代码语言:javascript
复制
class ProxyMiddleware(object):                
	def process_request(self, request, spider):
		# 代理服务器(产品官网 www.16yun.cn)
		proxyHost = "t.16yun.cn"
		proxyPort = "31111"
		# 代理验证信息
		proxyUser = "username"
		proxyPass = "password"
		request.meta['proxy'] = "http://{0}:{1}".format(proxyHost,proxyPort)
		# 添加验证头
		encoded_user_pass = base64ify(proxyUser + ":" + proxyPass)
		request.headers['Proxy-Authorization'] = 'Basic ' + encoded_user_pass                    
		# 设置IP切换头(根据需求)
		tunnel = random.randint(1,10000)
		request.headers['Proxy-Tunnel'] = str(tunnel)

session例,proxies为隧道代理

代码语言:javascript
复制
import requests

with requests.Session() as session:
	url="http://icanhazip.com/"
	response = session.get(url,timeout=20,proxies=proxies)
	print('ip1:',response.text)
	response = session.get(url,timeout=20,proxies=proxies)
	print('ip2:',response.text)

为什么隧道代理没有更换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

代码语言:javascript
复制
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)
代码语言:javascript
复制
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源码中就能找到对于连接复用的实现

代码语言:javascript
复制
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代码

代码语言:javascript
复制
# 使用隧道代理动态版发送请求
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)
代码语言:javascript
复制
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机制可以加快你的请求,需要您根据业务实际情况进行判断。

参考:https://shequ.codemao.cn/community/352779 https://mp.weixin.qq.com/s/4sRmhtezyO0_ZnuW_H7SXA https://blog.csdn.net/weixin_44617651/article/details/132274278

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-05-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用隧道转发爬虫代理保持IP/切换IP
  • 为什么隧道代理没有更换IP
    • 持久连接
      • HTTP客户端举例
        • Python-Requests
        • Python-Scrapy
      • 原因
        • 解决方法
          • 总结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档