1.在开通隧道代理IP后,单击网站右上角的【控制台】,进入后台管理面板,在左侧栏目里选择【代理IP】-【按时/按量业务】,找到已经开通的隧道代理业务;
2.隧道代理无须提取IP,接入隧道服务即可;
3.参考代码样例请求隧道代理;
4.在程序中通过调用API接口获取代理,然后请求目标网站。
(1)API调用需要验证,验证方式包括密钥验证和白名单验证,根据实际使用自主选择;
(2)密钥验证方式请求头带AuthKey和AuthPwd信息即可;
(3)添加白名单可以免密,添加白名单后大概在30s之后生效。
隧道不支持API的调用,只有白名单功能的API接口。
接口类型 | 接口 |
---|---|
白名单相关 | 添加白名单IP 删除白名单IP 查询白名单IP |
隧道代理支持密钥验证和白名单两种验证方式,建议先在本机测试;
需要注意的是,隧道代理(动态请求)的请求不超过购买时选择的每秒并发数,支持短期高并发;
隧道代理(固定时长)的同时可用请求不超过购买时选择的通道数,测试OK后就可以正常使用了。
如果用户需要多个请求在维持一个IP,比如:需要登录,获取数据两个请求在一个IP下,则可对IP进行打标记,通过标记请求在代理有效期内使用相同的代理IP。
隧道代理(固定时长)需要同时使用多IP,也需要对多个IP打标记,方便识别与使用。
查看代码示例 >
HTTP返回码 | 说明 |
---|---|
400 | 客户端错误。客户端协议无法被识别; |
431 | 请求头过大。出现在http代理中,header头部信息过多导致; |
302 | 出现302一般有两种情况: (1).客户端IP为海外IP,服务器会重定向到预警页面; (2).客户端访问的目标站被拦截,比如银行网站、邮箱、社交软件等,服务器返回重定向到预警页面; |
407 | 授权错误,出现407一般有两种情况: (1).白名单模式,可能是用户有多出口IP,没有全部添加到白名单;或可能连接使用IP资源,是添加白名单前获取的,白名单未对其生效; (2).账密模式,可能是账密信息错误; (3)共享IP产品中可能是IP已过期; |
408 | 目标站不可达。服务端与目标站建连失败,服务端不可达或者当前代理IP掉线; |
429 | 请求数超出。隧道产品中用户QPS大于购买的请求数;独享和共享产品中,用户当前的代理tcp连接超出限制数; |
508 | 代理目标站为代理IP地址导致死循环。一般不出现; |
503 | 当前代理协议不支持,比如ss代理协议; |
代理请求数据统计包括IP请求统计,提供了对请求量和请求错误的统计分析。方便随时关注采集程序的运行情况,及时发现错误并修正。
同时IP请求统计还提供几种常见的错误类型分析,如请求成功、授权失败、请求数超出、连接超时等,助力数据高效采集。
调用API
1.在开通静态独享代理IP后,单击网站右上角的【控制台】,可进入后台管理面板,在左侧栏目里选择【代理IP】-【按时/按量业务】,找到已经开通的静态独享代理业务;
2.在业务列表选择【操作-提取IP】,或提取工具或调试工具上选择对应的key提取IP,先进行本地调试和验证;
3.参考代码样例请求静态独享代理;
4.在程序中通过调用API接口获取代理,然后请求目标网站。
(1)API调用需要验证,验证方式包括密钥验证和白名单验证,根据实际使用自主选择;
(2)密钥验证方式请求头带AuthKey和AuthPwd信息即可;
(3)添加白名单可以免密,添加完白名单,立即对已申请的IP生效。
接口类型 | API |
---|---|
资源相关 | 提取资源 查询资源 提取并查询资源 查询通道数 查询地区和运营商 |
白名单相关 | 添加白名单IP 删除白名单IP 查询白名单IP |
IP数量和时长可自主控制,存活时长24小时起,24小后可释放申请新的IP,一周自主更换2次。
静态独享代理支持密钥验证和白名单两种验证方式,建议先在本机测试,测试OK后就可以正常使用了。
HTTP返回码 | 说明 |
---|---|
400 | 客户端错误。客户端协议无法被识别; |
431 | 请求头过大。出现在http代理中,header头部信息过多导致; |
302 | 出现302一般有两种情况: (1).客户端IP为海外IP,服务器会重定向到预警页面; (2).客户端访问的目标站被拦截,比如银行网站、邮箱、社交软件等,服务器返回重定向到预警页面; |
407 | 授权错误,出现407一般有两种情况: (1).白名单模式,可能是用户有多出口IP,没有全部添加到白名单;或可能连接使用IP资源,是添加白名单前获取的,白名单未对其生效; (2).账密模式,可能是账密信息错误; (3)共享IP产品中可能是IP已过期; |
408 | 目标站不可达。服务端与目标站建连失败,服务端不可达或者当前代理IP掉线; |
429 | 请求数超出。隧道产品中用户QPS大于购买的请求数;独享和共享产品中,用户当前的代理tcp连接超出限制数; |
508 | 代理目标站为代理IP地址导致死循环。一般不出现; |
503 | 当前代理协议不支持,比如ss代理协议; |
代理请求数据统计包括IP请求统计、IP提取明细,提供了对请求量和请求提取的统计和记录。方便随时关注采集程序的运行情况,及时发现错误并修正。
同时IP请求统计还提供几种常见的错误类型分析,如请求成功、授权失败、请求数超出、连接超时等,助力数据高效采集。
调用API
代码示例
开发者可以通过如下4个步骤使用动态独享代理
在开通动态独享代理产品后,单击网站右上角的【控制台】,进入后台管理面板,在左侧栏目里选择【代理IP】-【按时/按量业务】,找到已经开通的动态独享代理业务;
参考代码样例请求动态独享代理。
在程序中通过调用API接口获取代理,然后请求目标网站。
接口类型 | 接口 |
---|---|
动态独享代理 | 提取资源 查询资源 提取并查询资源 查询通道数 查询地区和运营商 |
动态独享代理(启用地区锁) | 提取资源 查询资源 提取并查询资源 查询通道数 查询地区和运营商 |
白名单相关 | 添加白名单IP 删除白名单IP 查询白名单IP |
动态独享代理支持密钥验证和白名单两种验证方式,建议先在本机测试,测试OK后就可以正常使用了。
地区锁指的是用户可以锁定地区IP进行切换,不会因为资源紧张而出现提取不到指定地区IP的情况。适合于需要使用固定地区家庭IP的场景。
启用地区锁后,提取速度会降低,使用方式也会改变。
HTTP返回码 | 说明 |
---|---|
400 | 客户端错误。客户端协议无法被识别; |
431 | 请求头过大。出现在http代理中,header头部信息过多导致; |
302 | 出现302一般有两种情况: 1.客户端IP为海外IP,服务器会重定向到预警页面 2.客户端访问的目标站被拦截,比如银行网站、邮箱、社交软件等,服务器返回重定向到预警页面 |
407 | 授权错误,出现407一般有两种情况: 1.白名单模式,可能是用户有多出口IP,没有全部添加到白名单;或可能连接使用IP资源,是添加白名单前获取的,白名单未对其生效 2.账密模式,可能是账密信息错误 3.共享IP产品中可能是IP已过期 |
408 | 目标站不可达。服务端与目标站建连失败,服务端不可达或者当前代理IP掉线 |
429 | 请求数超出。隧道产品中用户QPS大于购买的请求数;独享和共享产品中,用户当前的代理tcp连接超出限制数 |
508 | 代理目标站为代理IP地址导致死循环。一般不出现 |
503 | 当前代理协议不支持,比如ss代理协议 |
代理请求数据统计包括IP请求统计、IP提取明细,提供了对请求量和请求提取、使用的统计和记录。方便随时关注采集程序的运行情况,及时发现错误并修正。
同时IP请求统计还提供几种常见的错误类型分析,如请求成功、授权失败、请求数超出、连接超时等,助力数据高效采集。
调用API
代码示例
SDK下载
1.在购买动态共享代理产品后,单击网站右上角的【控制台】,进入后台管理面板,在左侧栏目里选择【代理IP】-【按时/按量业务】,找到已经开通的动态共享代理业务;
2.在业务列表选择【操作】-【提取IP】,或【提取工具】或【调试工具】上选择对应的key提取IP,进行本地调试和验证;
需要注意的是,按量动态共享提取IP不收费,使用IP才收费。IP的初始免费提取额度为1000个,之后每使用一个IP,新增5个提取额度,每10分钟后重置一次免费提取额度;
IP有效时长从提取时开始计算,提取后需尽快使用,以免IP过期;
3.参考代码样例请求动态共享代理;
4.在程序中通过调用API接口获取代理,然后请求目标网站。
(1) API调用需要验证,验证方式包括密钥验证和白名单验证,根据使用自主选择;
(2) 密钥验证方式请求头带AuthKey和AuthPwd信息即可;
(3) 添加白名单可以免密,需要在未提取IP之前添加白名单。需要注意的是,动态共享产品的不同key,不能添加相同的白名单IP。
动态共享代理(按时)API接口一览
接口类型 | 接口 |
---|---|
资源相关 | 提取资源 查询资源 提取并查询资源 查询通道数 查询地区和运营商 |
白名单相关 | 添加白名单IP 删除白名单IP 查询白名单IP |
动态共享代理(按量)API接口一览
接口类型 | 接口 |
---|---|
资源相关 | 提取资源 查询余额 查询地区和运营商 |
白名单相关 | 添加白名单IP 删除白名单IP 查询白名单IP |
动态共享代理支持密钥验证和白名单两种验证方式,建议先在本机测试,测试OK后就可以正常使用了。
HTTP返回码 | 说明 |
---|---|
400 | 客户端错误。客户端协议无法被识别; |
431 | 请求头过大。出现在http代理中,header头部信息过多导致; |
302 | 出现302一般有两种情况: (1)客户端IP为海外IP,服务器会重定向到预警页面; (2)客户端访问的目标站被拦截,比如银行网站、邮箱、社交软件等,服务器返回重定向到预警页面; |
407 | 授权错误,出现407一般有两种情况: (1) 白名单模式,可能是用户有多出口IP,没有全部添加到白名单;或可能连接使用IP资源,是添加白名单前获取的,白名单未对其生效; (2) 账密模式,可能是账密信息错误; (3)共享IP产品中可能是IP已过期; |
408 | 目标站不可达。服务端与目标站建连失败,服务端不可达或者当前代理IP掉线; |
429 | 请求数超出。隧道产品中用户QPS大于购买的请求数;独享和共享产品中,用户当前的代理tcp连接超出限制数; |
508 | 代理目标站为代理IP地址导致死循环,一般不出现; |
503 | 当前代理协议不支持,比如ss代理协议; |
代理请求数据统计包括IP请求统计、IP提取明细和IP使用记录,提供了对请求量和请求提取和使用的统计与记录。方便随时关注采集程序的运行情况,及时发现错误并修正。
同时请求统计还提供几种常见的错误类型分析,如请求成功、授权失败、请求数超出、连接超时等,助力数据高效采集。
调用API
代码示例
飞网账号登录,进入会员中心,选择“代理IP”模块,根据购买的按量业务或按时业务,查看您的所有代理业务;
通过添加白名单IP,业务可以免帐密使用代理IP,方便快捷。
需要注意的是每个业务的白名单需要单独设置,同时需要在使用代理IP前设置白名单才能有效应用与业务;
1.2.1 查询您将使用代理的机器的外网IP;
如果是办公室电脑,可以访问https://ip.cn/api/index?ip=&type=0查询您的外网IP ;
如果是Linux服务器,可以通过如下命令查看机器外网IP:curl myipip.net
1.2.2 在会员中心—代理IP—按时业务/按量业务—操作点击“白名单”,进行白名单管理,如下图:
1.2.3 输入您的外网IP,点击“添加”即可;
1.3.1 进入会员中心,在代理IP业务列表中选择要使用的业务,点击“提取IP”;
1.3.2 选择提取的IP数量、存活周期、地区等要素,默认随机,数量和存活周期不可超过业务最大值;
复制提取的IP与端口号,根据您的使用场景和设备,选择合适的设置代理方式。
手机/平板 | 电脑 | 软件 | 浏览器 |
---|---|---|---|
安卓 | Windows 10 | 花刺代理 | 360浏览器 |
iPhone/iPad | Windows 7 | SocksCap64 | 谷歌浏览器 |
Mac | Proxifier | 搜狗浏览器 | |
火狐浏览器 |
飞网代理IP使用验证包括帐密验证和白名单,帐密验证需要每次使用进行验证,建议用户优先使用白名单;
帐密验证具体流程如下:
2.1.1 进入会员中心,在代理IP业务列表中选择要使用的业务,点击“管理”查看业务密钥,如下图:
2.1.2 使用代理IP进行帐密身份验证,根据提示对应输入用户名(Authkey)和密码(Authpwd),如下图:
全局代理:设置全局代理后,电脑的整个网络都使用的是代理。
局部代理:只是针对指定的浏览器或软件使用代理,其他软件不受影响。
静态独享、动态共享和动态独享通过API获取代理IP列表后,您就可以在程序里通过代理服务器获取网页数据。
隧道代理无需调用API获取代理,在会员中心查看隧道的IP和端口号。
您获取的代理IP是这样的:122.96.59.105:23068
122.96.59.105
是代理服务器的IP地址;23068
是代理服务器的端口号。
使用静态独享、动态独享和动态共享的IP需要进行授权验证,购买后只有通过您的用户名密码或设置您的IP白名单后才能使用。
隧道共享则是通过访问飞网隧道服务器,服务器访问只对您的业务授权使用,同时支持用户名密码(Authkey和Authpwd)和IP白名单。
我们支持两种验证方式:
如果是办公室电脑,可以访问https://ip.cn/api/index?ip=&type=0查询您的外网IP;
如果是Linux服务器,可以通过如下命令查看机器外网IP:curl myipip.net
进入会员中心,找到您所在的业务,管理白名单(包括添加删除白名单),白名单设置详情如下图:
进入会员中心,在您所在的代理IP业务找到用于代理IP验证的用户名密钥信息(Authkey和Authpwd)。
(1).HTTP代理
通过用户名密码的进行身份认证,格式如下:
curl -x http://{key}:{passwd}@{ip}:{port} {targetUrl}
http/https代理,-x 填写的协议头只能是http,不能是https,如果填写下面那样的格式,将无法访问
curl -x https://{ip}:{port} {targetUrl}
(2).SOCKS代理
curl -x socks5://{ip}:{port} {targetUrl}
curl返回的是未渲染的html内容,这属于正常现象。
如果您的程序在Linux上运行,我们非常推荐您在命令行下先通过curl
命令测试代理服务器的可用性,然后再进行编程。
例如您的用户名是authkey
,密码是authpwd
,提取到的代理IP是118.92.69.112:32105
,IP白名单是36.90.191.92:32140
,可执行如下命令测试代理可用性:
http/https代理,帐密模式
curl -x http://{authkey}:{authpwd}@{118.92.69.112}:{32105} {targetUrl}
http/https代理,白名单模式
curl -x http://{36.90.191.92}:{32140} {targetUrl}
此示例Python使用Selenium调用Chrome浏览器并通过代理进行自动化测试。
import time
import string
import zipfile
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
targetURL = "http://myip.ipip.net" # 访问的目标站点
proxyHost = "61.171.76.145" # 代理IP地址
proxyPort = "50353" # 代理IP端口号
authKey = "x" # 代理IP的AuthKey
password = "x" # 代理IP的AuthPwd
def create_proxy_auth_extension(proxy_host, proxy_port, proxy_username, proxy_password, scheme='http',
plugin_path=None):
if plugin_path is None:
plugin_path = r'./{}_{}_qgnet_proxyauth_plugin.zip'.format(proxy_username, proxy_password)
manifest_json = """
{
"version": "1.0.0",
"manifest_version": 2,
"name": "Chrome Proxy",
"permissions": [
"proxy",
"tabs",
"unlimitedStorage",
"storage",
"",
"webRequest",
"webRequestBlocking"
],
"background": {
"scripts": ["background.js"]
},
"minimum_chrome_version":"22.0.0"
}
"""
background_js = string.Template(
"""
var config = {
mode: "fixed_servers",
rules: {
singleProxy: {
scheme: "${scheme}",
host: "${host}",
port: parseInt(${port})
},
bypassList: ["localhost"]
}
};
chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});
function callbackFn(details) {
return {
authCredentials: {
username: "${username}",
password: "${password}"
}
};
}
chrome.webRequest.onAuthRequired.addListener(
callbackFn,
{urls: [""]},
['blocking']
);
"""
).substitute(
host=proxy_host,
port=proxy_port,
username=proxy_username,
password=proxy_password,
scheme=scheme,
)
with zipfile.ZipFile(plugin_path, 'w') as zp:
zp.writestr("manifest.json", manifest_json)
zp.writestr("background.js", background_js)
return plugin_path
if __name__ == '__main__':
# 此处指定您的webdriver路径,版本需要跟您所使用的Chrome版本一致,
# 下载地址https://registry.npmmirror.com/binary.html?path=chromedriver/
driver_location = "./chromedriver/chromedriver_v106_win.exe"
proxy_auth_plugin_path = create_proxy_auth_extension(
proxy_host=proxyHost,
proxy_port=proxyPort,
proxy_username=authKey,
proxy_password=password)
option = webdriver.ChromeOptions()
option.add_argument("--start-maximized") # 窗口最大化运行
option.add_extension(proxy_auth_plugin_path) # 添加proxy插件
# 此处selenium版本为4.8.0
driver = webdriver.Chrome(service=Service(driver_location), options=option)
driver.get(targetURL)
time.sleep(100)
driver.quit()
此示例Python使用Selenium调用Chrome浏览器并通过代理进行自动化测试。
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
targetURL = "http://myip.ipip.net" #访问的目标站点
proxyAddr = "您的代理IP:端口号"
if __name__ == '__main__':
browser_location = r".\Chrome\chrome.exe" #指定浏览器路径位置
driver_location = r".\Chrome\chromedriver.exe" #指定Driver路径位置
option = webdriver.ChromeOptions()
option.binary_location = browser_location #设置浏览器位置
option.add_argument("--start-maximized") #窗口最大化运行
option.add_argument('--proxy-server=%(server)s' % {"server": proxyAddr})
driver = webdriver.Chrome(service=Service(driver_location), options=option)
driver.get(targetURL)
print(driver.page_source)
import base64
import time
import requests
from requests.adapters import HTTPAdapter
auth_key = "请改成您的Key"
password = "请改成您的AuthPwd"
tunnel_server = "http://请改成您的隧道地址" # 如:tunnel3.qg.net:19263
target_url = "https://ip.cn/api/index?ip=&type=0" # 要访问的目标地址
proxy_headers = {}
proxy = {
"http": tunnel_server,
"https": tunnel_server
}
def encode_authorization(key, passwd):
# python 使用 bytes 类型进行 base64 编码
basic_str = bytes("%s:%s" % (key, passwd), "ascii")
# 得到的返回值也是 bytes 类型,所以需要再 decode 为字符串
return "Basic %s" % base64.b64encode(basic_str).decode("utf-8")
def reset_tunnel_proxy_headers():
global proxy_headers
proxy_headers = {
tunnel_server: {
"Proxy-Authorization": encode_authorization(auth_key, password)
}
}
def update_tunnel_proxy_headers(key, val):
global proxy_headers
proxy_headers[tunnel_server][key] = val
def new_session():
adapter = TunnelProxyAdapter()
se = requests.Session()
se.mount('https://', adapter)
se.mount('http://', adapter)
return se
class TunnelProxyAdapter(requests.adapters.HTTPAdapter):
def proxy_headers(self, p):
if p in proxy_headers:
print("session with headers:", proxy_headers[p])
return proxy_headers[p]
else:
return None
def multi_channel_tunnel():
"""
结果类似:
request on multi channel
request id: 1 , channel id: channel-1, code: 200, result: 183.155.88.224
request id: 2 , channel id: channel-2, code: 200, result: 125.112.38.153
request id: 3 , channel id: channel-3, code: 200, result: 183.155.89.125
request id: 4 , channel id: channel-4, code: 200, result: 49.71.121.169
request id: 5 , channel id: channel-5, code: 200, result: 115.210.67.220
request id: 6 , channel id: channel-6, code: 200, result: 36.25.41.178
request id: 7 , channel id: channel-7, code: 200, result: 180.125.162.116
request id: 8 , channel id: channel-8, code: 200, result: 140.250.150.158
request id: 9 , channel id: channel-9, code: 200, result: 121.227.102.227
request id: 10, channel id: channel-10, code: 200, result: 49.88.106.198
request id: 1 , channel id: channel-1, code: 200, result: 183.155.88.224
request id: 2 , channel id: channel-2, code: 200, result: 125.112.38.153
request id: 3 , channel id: channel-3, code: 200, result: 183.155.89.125
request id: 4 , channel id: channel-4, code: 200, result: 49.71.121.169
request id: 5 , channel id: channel-5, code: 200, result: 115.210.67.220
request id: 6 , channel id: channel-6, code: 200, result: 36.25.41.178
request id: 7 , channel id: channel-7, code: 200, result: 180.125.162.116
request id: 8 , channel id: channel-8, code: 200, result: 140.250.150.158
request id: 9 , channel id: channel-9, code: 200, result: 121.227.102.227
request id: 10, channel id: channel-10, code: 200, result: 49.88.106.198
"""
print("request on multi channel")
reset_tunnel_proxy_headers()
for i in range(1, 11):
se = new_session()
chan_id = "channel-%s" % i
update_tunnel_proxy_headers("Proxy-TunnelID", chan_id)
resp = se.get(target_url, proxies=proxy, headers={"Connection": "close"})
print("request id: %-2s, channel id: %s, code: %s, result: %s" % (i, chan_id, resp.status_code, resp.text))
time.sleep(10)
# 因为固定时长为1分钟,所以在1分钟内继续使用已有通道,仍是之前的IP
for i in range(1, 11):
se = new_session()
chan_id = "channel-%s" % i
update_tunnel_proxy_headers("Proxy-TunnelID", chan_id)
resp = se.get(target_url, proxies=proxy, headers={"Connection": "close"})
print("request id: %-2s, channel id: %s, code: %s, result: %s" % (i, chan_id, resp.status_code, resp.text))
if __name__ == "__main__":
multi_channel_tunnel()
package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"sync"
"time"
)
/** 返回内容
第一次循环
当前 IP:121.230.91.188 来自于:中国 江苏 泰州 电信
当前 IP:60.184.205.115 来自于:中国 浙江 丽水 电信
当前 IP:125.112.205.149 来自于:中国 浙江 金华 电信
当前 IP:60.184.108.175 来自于:中国 浙江 丽水 电信
当前 IP:58.214.87.31 来自于:中国 江苏 无锡 电信
当前 IP:183.143.131.24 来自于:中国 浙江 湖州 电信
当前 IP:42.53.99.119 来自于:中国 辽宁 锦州 联通
当前 IP:59.60.142.70 来自于:中国 福建 漳州 电信
当前 IP:114.226.175.159 来自于:中国 江苏 常州 电信
当前 IP:123.162.194.223 来自于:中国 河南 驻马店 电信
max channel reached
第二次循环
当前 IP:114.226.175.159 来自于:中国 江苏 常州 电信
当前 IP:60.184.205.115 来自于:中国 浙江 丽水 电信
当前 IP:121.230.91.188 来自于:中国 江苏 泰州 电信
当前 IP:125.112.205.149 来自于:中国 浙江 金华 电信
当前 IP:123.162.194.223 来自于:中国 河南 驻马店 电信
当前 IP:58.214.87.31 来自于:中国 江苏 无锡 电信
当前 IP:183.143.131.24 来自于:中国 浙江 湖州 电信
当前 IP:60.184.108.175 来自于:中国 浙江 丽水 电信
当前 IP:59.60.142.70 来自于:中国 福建 漳州 电信
当前 IP:42.53.99.119 来自于:中国 辽宁 锦州 联通
第二次循环返回的IP与第一次循环相同,因为goroutine是异步的,所以返回顺序和第一次不一致
myip.ipip.net服务器可能比较容易失败,用户可以自己找一个其他获取客户端IP的服务器来测试
*/
// 固定时长多通道隧道模式
func main() {
authKey := "请改成您的Key" //固定时长1分钟的隧道,通道数10
password := "请改成您的AuthPwd"
proxyServer := "请改成您的隧道地址" //如:tunnel3.qg.net:19263
targetURL := "https://ip.cn/api/index?ip=&type=0"
rawURL := fmt.Sprintf("http://%s:%s@%s", authKey, password, proxyServer)
proxyUrl, _ := url.Parse(rawURL)
wg := sync.WaitGroup{}
wg.Add(11)
// 十个通道分别使用不同的十个IP,第十一次会返回错误,通道数超出
for i := 0; i < 11; i++ {
go func(index int) {
defer wg.Done()
client := http.Client{
Transport: &http.Transport{
ProxyConnectHeader: http.Header{
"Proxy-TunnelID": []string{fmt.Sprintf("channel-%d", index)}, // 指定通道ID
},
Proxy: http.ProxyURL(proxyUrl),
},
}
req, _ := http.NewRequest("GET", targetURL, nil)
rsp, err := client.Do(req)
if err != nil {
fmt.Printf("request failed: %s\n", err)
return
}
defer rsp.Body.Close()
body, err := ioutil.ReadAll(rsp.Body)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(string(body))
}
}(i)
}
wg.Wait()
// 因为固定时长为1分钟,所以在1分钟内继续使用已有通道,仍是之前的IP
time.Sleep(time.Second * 10)
wg.Add(10)
for i := 0; i < 10; i++ {
go func(index int) {
defer wg.Done()
client := http.Client{
Transport: &http.Transport{
ProxyConnectHeader: http.Header{
"Proxy-TunnelID": []string{fmt.Sprintf("channel-%d", index)}, // 指定通道ID
},
Proxy: http.ProxyURL(proxyUrl),
},
}
req, _ := http.NewRequest("GET", targetURL, nil)
rsp, err := client.Do(req)
if err != nil {
fmt.Printf("request failed: %s\n", err)
return
}
defer rsp.Body.Close()
body, err := ioutil.ReadAll(rsp.Body)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(string(body))
}
}(i)
}
wg.Wait()
}