代码样例-HTTP隧道

本文档包含编程请求http隧道的代码样例,供开发者参考。

代码样例使用说明

  1. 代码样例不能直接运行,因为代码中的隧道服务器ip:port、用户名username、密码password都是虚构的,请替换成您自己的信息。
  2. 隧道代理不需要使用API链接等其他方式获取代理IP,所有请求将在隧道服务器上进行更换IP并转发。
  3. 建议关闭HTTP协议的keep-alive功能,避免因连接复用导致隧道不能切换IP。
  4. 代码样例正常运行所需的运行环境和注意事项在样例末尾均有说明,使用前请仔细阅读。
  5. 使用代码样例过程中遇到问题请联系售后客服,我们会为您提供技术支持。

特别注意

以下代码样例均为基础样例,运行基础样例并不能保证成功爬取目标网站。目标网站通常具备反爬机制,比如跳转需要输入验证码的页面。

我们建议您在开发过程中基于基础样例进行如下改进:

  1. 合理控制对目标网站的请求频率,建议对同一网站1个代理IP每秒请求不超过1次;
  2. 发出的http请求尽可能带上完整的header信息。

Python3

requests

requests(推荐)

使用提示

  1. 基于requests的代码样例支持访问http,https网页,推荐使用
  2. requests不是python原生库,需要安装才能使用: pip install requests
import requests

# 隧道域名:端口号
tunnel = "address:port"

# 用户名密码方式
username = "username"
password = "password"
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}
}

# 白名单方式(需提前设置白名单)
#proxies = {
#    "http": "http://%(proxy)s/" % {"proxy": tunnel},
#    "https": "http://%(proxy)s/" % {"proxy": tunnel}
#}

# 要访问的目标网页
target_url = "http://www.xx.com"

# 使用隧道域名发送请求
response = requests.get(target_url, proxies=proxies)

# 获取页面内容
if response.status_code == 200:
    print(response.text)  # 请勿使用keep-alive复用连接(会导致隧道不能切换IP)

aiohttp

aiohttp

使用提示

  1. 基于aiohttp的代码样例支持访问http,https网页
  2. aiohttp不是python原生库,需要安装才能使用: pip install aiohttp
  3. aiohttp只支持Python3.5及以上
  4. 如Windows系统使用aiohttp访问https网站抛出异常,在import asyncio后调用 asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())即可解决。
import aiohttp
import asyncio
# asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) # windows系统请求https网站报错时调用此方法

page_url = "http://www.xx.com"  # 要访问的目标网页

# 隧道域名:端口号
tunnel = "address:port"

# 用户名和密码方式
# username = "username"
# password = "password"

# proxy_auth = aiohttp.BasicAuth(username, password)

# 账密
# async def fetch(session, url):
#    async with session.get(url, proxy="http://"+tunnel, proxy_auth=proxy_auth) as response:
#        return await response.text()

# 白名单
async def fetch(session, url):
    async with session.get(url, proxy="http://"+tunnel) as response:
        return await response.text()
async def main():
    # aiohttp默认使用严格的HTTPS协议检查。可以通过将ssl设置为False来放松认证检查
    # async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False)) as session:
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, page_url)
        print(html)

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

httpx

httpx

使用提示

  1. 基于httpx的代码样例支持访问http,https网页
  2. httpx不是python原生库,需要安装才能使用: pip install httpx
  3. httpx运行环境要求 Python3.7+
  4. httpx暂时还不支持SOCKS代理
import httpx

# 隧道域名:端口号
tunnel = "address:port"

# 用户名和密码方式
username = "username"
password = "password"

# proxy_url = "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": tunnel}
proxy_url = "http://%(proxy)s/" % {"proxy": tunnel}

proxies = httpx.Proxy(
    url=proxy_url
)

with httpx.Client(proxies=proxies) as client:
    r = client.get('http://www.xx.com')
    print(r.text)

urllib

urllib

使用提示

  1. 基于urllib的代码样例同时支持访问http和https网页
  2. 运行环境要求 python3.x
import urllib.request
import ssl

# 全局取消证书验证,避免访问https网页报错
ssl._create_default_https_context = ssl._create_unverified_context

# 隧道域名:端口号
tunnel = "address:port"

# 用户名密码方式
username = "username"
password = "password"
# 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}
#}

# 白名单方式(需提前设置白名单)
proxies = {
     "http": "http://%(proxy)s/" % {"proxy": tunnel},
     "https": "http://%(proxy)s/" % {"proxy": tunnel}
}

# 要访问的目标网页
target_url = "http://www.xx.com"

# 使用隧道域名发送请求
proxy_support = urllib.request.ProxyHandler(proxies)
opener = urllib.request.build_opener(proxy_support)
# urllib.request.install_opener(opener)   注意此处是全局设置代理,如用这种写法进程内之后的所有urllib请求都会使用代理
# response = urllib.request.urlopen(target_url)
response = opener.open(target_url)

# 获取页面内容
if response.code == 200:
    print(response.read().decode('utf-8'))

httpclient

httpclient(IP白名单)

使用提示

  1. 基于httpclient的代码样例同时支持访问http和https网页
import http.client

# 代理服务器的地址和端口
proxy_host = "address"
proxy_port = port

# 目标服务器的地址
target_host = "www.xx.com"

# 创建连接对象
conn = http.client.HTTPSConnection(proxy_host, proxy_port)

# 设置代理信息
conn.set_tunnel(target_host)

# 发送请求
conn.request("GET", "/")

# 获取响应
response = conn.getresponse()

# 打印响应状态和内容
print(response.status, response.reason)
print(response.read().decode('utf-8'))

# 关闭连接
conn.close()

socket

socket

使用提示

  1. 基于socket的代码样例支持访问http,https网页
  2. socks不是python原生库,需要安装才能使用: pip install PySocks
  3. 使用socket发起http请求需要按http协议格式完整构造http request

                            

pyppeteer

pyppeteer

使用提示

  1. 基于pyppeteer的代码样例支持访问http,https网页
  2. pyppeteer不是python原生库,需要安装才能使用: pip install pyppeteer
  3. pyppeteer只支持Python3.5及以上
  4. pyppeteer是异步渲染网页,需要使用asyncio等库
import asyncio
from pyppeteer import launch
# 隧道服务器
proxy_raw = "address:port"

def accounts():
    # 用户名密码, 若已添加白名单则不需要添加
    username = "username"
    password = "password"
    account = {"username": username, "password": password}
    return account


async def main():
    # 要访问的目标网页
    target_url = "http://www.xx.com"
    browser = await launch({
        'headless': False,
        'executablePath': r"C:\chrome.exe",
        'ignorehttpserrrors': True,
        'args': ['--disable-infobars', '--proxy-server=' + proxy_raw]})
    page = await browser.newPage()

    # await page.authenticate(accounts())  # 白名单方式,注释本行(需提前设置白名单)
    await page.setViewport({'width': 1920, 'height': 1080})
    # 使用代理IP发送请求
    await page.goto(target_url)
    await asyncio.sleep(209)
    await browser.close()

asyncio.get_event_loop().run_until_complete(main())

playwright

playwright

使用提示

  1. 基于playwright的代码样例支持访问http,https网页
  2. playwright不是python原生库,需要安装才能使用: pip install playwright
  3. 如果您的计算机上没有支持的浏览器,需要执行 playwright install 以安装依赖文件
  4. playwright只支持Python3.7及以上
  5. playwright支持同步或异步执行,以下为同步执行示例
import requests
from playwright.sync_api import sync_playwright

proxy_ip = "隧道域名:端口号"

# 用户名密码方式
username = "username"
password = "password"

# 要访问的目标网页
url = "http://www.xx.com"

proxies = {
    "server": proxy_ip,
    "username": username,
    "password": password,
}

# 白名单方式(需提前设置白名单)
# proxies = {
#    "server": proxy_ip,
# }

with sync_playwright() as playwright:
    # headless=True 无头模式,不显示浏览器窗口
    browser = playwright.chromium.launch(headless=False, proxy=proxies, executable_path='C:\\chrome.exe')
    context = browser.new_context()
    page = context.new_page()
    page.goto(url)
    content = page.content()
    print(content)
    # other actions...
    browser.close()

Python2

requests

requests(推荐)

使用提示

  1. 基于requests的代码样例支持访问http,https网页,推荐使用
  2. requests不是python原生库,需要安装才能使用: pip install requests
import requests

tunnel = "address:port"

username = "username"
password = "password"
# 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}
#}

proxies = {
    "http": "http://%(proxy)s/" % {"proxy": tunnel},
    "https": "http://%(proxy)s/" % {"proxy": tunnel}
}

target_url = "http://www.xxx.com"

response = requests.get(target_url, proxies=proxies)

if response.status_code == 200:
    print response.text

urllib2

urllib2

使用提示

  1. 基于urllib2的代码样例同时支持访问http和https网页
  2. 运行环境要求 python2.6 / 2.7
import urllib2
import ssl

ssl._create_default_https_context = ssl._create_unverified_context

tunnel = "address:port"

username = "username"
password = "password"
# proxies = {
#    "http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": tunnel},
#    "https": "https://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": tunnel}
#}

proxies = {
     "http": "http://%(proxy)s/" % {"proxy": tunnel},
    "https": "https://%(proxy)s/" % {"proxy": tunnel}
}

target_url = "http://www.xx.com"

proxy_support = urllib2.ProxyHandler(proxies)
opener = urllib2.build_opener(proxy_support)
# urllib2.install_opener(opener)  注意此处是全局设置代理,如用这种写法进程内之后的所有urllib请求都会使用代理
# response = urllib2.urlopen(target_url)
response = opener.open(target_url)

if response.code == 200:
    print response.read()

Python-Selenium

Chrome

Chrome(IP白名单,推荐)

使用提示

  1. 基于白名单方式使用Selenium+Chrome认证代理
  2. 运行环境要求python2/3 + selenium + Chrome + Chromedriver + Windows/Linux/macOS
  3. 下载chromedriver(注意chromedriver版本要和Chrome版本对应)
  4. selenium不是python原生库,需要安装才能使用:pip install selenium (注意:selenium 4.6版本开始,无需手动下载driver)
  5. 请注意替换代码中的部分信息:
    tunnelhost:tunnelport:隧道域名:端口号
    ${chromedriver_path}:您本机chromedriver驱动存放路径,如:"C:\chromedriver.exe"
from selenium import webdriver
import time


chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--proxy-server=http://tunnelhost:tunnelport')
# selenium 4.6及以上
driver = webdriver.Chrome(options=chrome_options)
# ${chromedriver_path}: chromedriver驱动存放路径
# driver = webdriver.Chrome(executable_path="${chromedriver_path}", options=chrome_options)
driver.get("http://www.xx.com")

# 获取页面内容
print(driver.page_source)

# 延迟3秒后关闭当前窗口,如果是最后一个窗口则退出
time.sleep(3)
driver.close()

Chrome(用户名密码认证)

使用提示

  1. 基于用户名密码方式使用Selenium+Chrome认证代理
  2. 运行环境要求python2/3 + selenium + Chrome + Chromedriver + Windows/Linux/macOS
  3. 下载chromedriver(注意chromedriver版本要和Chrome版本对应)
  4. selenium不是python原生库,需要安装才能使用:pip install selenium (注意:selenium 4.6版本开始,无需手动下载driver)
  5. 请注意替换代码中的部分信息:
    ${tunnelhost:port}:隧道域名:端口号
    ${username}:用户名
    ${password}:密码
    ${chromedriver_path}:您本机chromedriver驱动存放路径,如:"C:\chromedriver.exe"


Firefox

Firefox(用户名密码认证)

使用提示

  1. 基于用户名密码方式使用Selenium-wire+Firefox认证代理
  2. 运行环境要求python3.4以上 + selenium-wire + Firefox + geckodriver + Windows/Linux/macOS
  3. 下载geckodriver(注意geckodriver版本要和Firefox版本对应)
  4. selenium-wire不是python原生库,需要安装才能使用:pip install selenium-wire
  5. 请注意替换代码中的部分信息:
    ${geckodriver_path}:您本机geckodriver驱动存放路径,如:"C:\geckodriver.exe"
import time
from seleniumwire import webdriver

proxyIp = '${tunnelhost:port}'
username = "${username}"
password = "${password}"

options = {
    'proxy': {
        "http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxyIp},
        "https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxyIp}
    }
}

# 白名单
# options = {
#    'proxy': {
#        "http": "http://%(proxy)s/" % {"proxy": proxyIp},
#        "https": "http://%(proxy)s/" % {"proxy": proxyIp}
#    }
# }

driver = webdriver.Firefox(seleniumwire_options=options,executable_path=${geckodriver_path})

driver.get('http://www.xx.com')

# 获取页面内容
print(driver.page_source)

# 延迟3秒后关闭当前窗口,如果是最后一个窗口则退出
time.sleep(3)
driver.close()

Python-DrissionPage

IP白名单,推荐

使用提示

  1. 基于白名单方式使用
  2. 运行环境要求 python3 + Windows/Linux
  3. 支持Chromium内核浏览器(如 Chrome 和 Edge)
  4. DrissionPage不是python原生库,需要安装才能使用:pip install DrissionPage

                            
用户名密码认证

使用提示

  1. 基于用户名密码方式使用
  2. 运行环境要求 python3 + Windows/Linux
  3. 支持Chromium内核浏览器(如 Chrome 和 Edge)
  4. DrissionPage不是python原生库,需要安装才能使用:pip install DrissionPage
  5. 请注意替换代码中的部分信息:
    tunnelhost:隧道域名
    tunnelport:端口号
    username:代理用户名
    password:代理密码

                            

Python-Scrapy

使用提示

  1. http/https 网页均可适用
  2. scrapy 不是 python 原生库,需要安装才能使用: pip install scrapy
  3. 在第一级 tutorial 目录下运行如下命令查看结果:scrapy crawl kdl
  4. Scrapy 在使用隧道代理可能会出现复用之前建立的连接导致不能正常更换IP,请在 header 中加入 Connection: close
Scrapy项目目录

运行命令:scrapy startproject tutorial 新建 Scrapy 项目,创建包含下列内容的 tutorial 目录


                            

kdl_spider.py

编写爬虫(Spider):在 tutorial/spiders/ 目录下新建 kdl_spider.py 文件


                            

middlewares.py
  1. middlewares.py 中新增 ProxyDownloaderMiddleware 即代理中间件
  2. 请注意替换代码中的部分信息:username:用户名,password:密码,*XXX.XXX.com:隧道域名
    
                                        
settings.py

settings.py中激活ProxyDownloaderMiddleware代理中间件


                            

Python-feapder

使用提示

  1. http/https 网页均可适用
  2. 运行环境要求 python3.6 以上
  3. feapder 不是 python 原生库,需要安装才能使用: pip install feapder
  4. 使用命令 feapder create -s py3_feapder 创建一个轻量爬虫
py3_feapder.py
  • py3_feapder.py 中新增 download_midware 方法,即下载中间件

                            

Java

okhttp3

okhttp-3.8.1

使用提示

  1. 此样例同时支持访问http和https网页
  2. 使用用户名密码访问的情况下,每次请求httpclient不会发送两次进行认证,与使用白名单效果相同
  3. 使用用户名密码验证时必须重写 Authenticatorauthenticate方法
  4. 依赖包下载:
    okhttp-3.8.1
  5. 建议关闭HTTP协议的keep-alive功能,避免因连接复用导致隧道不能切换IP。
import okhttp3.*;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
public class OkHttpTunnel {
	public static void main(String args[]) throws IOException {
		// 目标网站
		String targetUrl = "http://www.xx.com";

		// 用户名密码, 若已添加白名单则不需要添加
		final String username = "username";
		final String password = "password.";

		String ip = "隧道代理域名";
		int port = 端口号;

		Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ip, port));

		Authenticator authenticator = new Authenticator() {
			@Override
			public Request authenticate(Route route, Response response) throws IOException {
			String credential = Credentials.basic(username, password);
			return response.request().newBuilder()
				.header("Proxy-Authorization", credential)
				.build();
			}
		};
		OkHttpClient client = new OkHttpClient.Builder()
				.proxy(proxy)
				.proxyAuthenticator(authenticator)
				.build();
		
		Request request = new Request.Builder()
				.url(targetUrl)
				.addHeader("Connection","close")
				.build();
		
		Response response = client.newCall(request).execute();
		System.out.println(response.body().string());
		
	}
}

httpclient

HttpClient-4.5.13

使用提示

  1. 此样例同时支持访问http和https网页
  2. 使用用户名密码访问的情况下,每次请求httpclient会发送两次进行认证从而导致请求耗时增加,建议使用白名单访问
  3. 若有多个用户名、密码进行认证需要在代码中须添加AuthCacheValue.setAuthCache(new AuthCacheImpl());
  4. 依赖包下载:
    httpclient-4.5.13
    httpcore-4.4.13
    commons-codec-1.11
    commons-logging-1.2
import java.net.URL;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class HTTPClientTunnel {


        /**
         * 使用httpclient请求隧道服务器 请求http和https网页均适用
         */
        private static String pageUrl = "http://www.xx.com"; // 要访问的目标网页
        private static String proxyIp = "隧道服务器域名";
        private static int proxyPort = 端口号;
        // 用户名密码, 若已添加白名单则不需要添加
        private static String username = "username";
        private static String password = "password";

        public static void main(String[] args) throws Exception {
            // JDK 8u111版本后,目标页面为HTTPS协议,启用proxy用户密码鉴权
            System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");

            CredentialsProvider credsProvider = new BasicCredentialsProvider();
            //credsProvider.setCredentials(new AuthScope(proxyIp, proxyPort), new UsernamePasswordCredentials("", ""));
            credsProvider.setCredentials(new AuthScope(proxyIp, proxyPort),new UsernamePasswordCredentials(username, password));
            CloseableHttpClient httpclient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
            try {
                URL url = new URL(pageUrl);
                HttpHost target = new HttpHost(url.getHost(), url.getDefaultPort(), url.getProtocol());
                HttpHost proxy = new HttpHost(proxyIp, proxyPort);

	            /*
	            setConnectTimeout:设置连接超时时间
	            setConnectionRequestTimeout:设置从connect Manager获取Connection 超时时间
	            setSocketTimeout:请求获取数据的超时时间
	            */
                RequestConfig config = RequestConfig.custom().setProxy(proxy).setConnectTimeout(6000)
                        .setConnectionRequestTimeout(2000).setSocketTimeout(6000).build();
                HttpGet httpget = new HttpGet(url.getPath());
                httpget.setConfig(config);
                httpget.addHeader("Accept-Encoding", "gzip"); // 使用gzip压缩传输数据让访问更快
                httpget.addHeader("Connection", "close");
                httpget.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36");
                CloseableHttpResponse response = httpclient.execute(target, httpget);
                try {
                    System.out.println(response.getStatusLine());
                    System.out.println(response.toString());
                } finally {
                    response.close();
                }
            } finally {
                httpclient.close();
            }
        }

}

jsoup

使用jsoup发起请求

使用提示

  1. 此样例同时支持访问http和https网页
  2. 使用用户名密码访问的情况下,每次请求httpclient会发送两次进行认证从而导致请求耗时增加,建议使用白名单访问
  3. 若有多个用户名、密码进行认证需要在代码中须添加AuthCacheValue.setAuthCache(new AuthCacheImpl());
  4. 依赖包下载:
    jsoup-1.13.1
import java.io.IOException;
import java.net.Authenticator;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
public class JsoupProxy {

    // 用户名密码, 若已添加白名单则不需要添加
    final static String ProxyUser = "username";
    final static String ProxyPass = "password";

    // 代理隧道域名、端口号
    final static String ProxyHost = "代理隧道域名";
    final static Integer ProxyPort = 端口号;

    public static String getUrlProxyContent(String url) {
        Authenticator.setDefault(new Authenticator() {
            public PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(ProxyUser, ProxyPass.toCharArray());
            }
        });

        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ProxyHost, ProxyPort));

        try {
            // 此处自己处理异常、其他参数等
            Document doc = Jsoup.connect(url).followRedirects(true).timeout(3000).proxy(proxy).get();
            if (doc != null) {
                System.out.println(doc.body().html());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static void main(String[] args) throws Exception {
        // 目标网站
        String targetUrl = "http://www.xx.com";

        // JDK 8u111版本后,目标页面为HTTPS协议,启用proxy用户密码鉴权
        System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");

        getUrlProxyContent(targetUrl);
    }
}

hutool

使用hutool发起请求

使用提示

  1. 此样例同时支持访问http和https网页
  2. 使用用户名密码访问的情况下,每次请求httpclient会发送两次进行认证从而导致请求耗时增加,建议使用白名单访问
  3. 依赖包下载:
    hutool-all-5.8.16
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpRequest;

public class HuToolProxy {

        // 用户名密码, 若已添加白名单则不需要添加
        final static String ProxyUser = "username";
        final static String ProxyPass = "password";

        // 代理隧道域名、端口号
        final static String ProxyHost = "代理隧道域名";
        final static Integer ProxyPort = 端口号;

        public static void main(String[] args) {
            // 目标网站
            String url = "https://www.xx.com";
            // JDK 8u111版本后,目标页面为HTTPS协议,启用proxy用户密码鉴权
            System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
            // 设置请求验证信息
            Authenticator.setDefault(new ProxyAuthenticator(ProxyUser, ProxyPass));

            // 发送请求
            HttpResponse result = HttpRequest.get(url)
                    .setHttpProxy(ProxyHost, ProxyPort)
                    .timeout(6000)//设置超时,毫秒
                    .execute();
            System.out.println(result.body());
        }
}
// 代理验证信息
class ProxyAuthenticator extends Authenticator {
    private String user, password;

    public ProxyAuthenticator(String user, String password) {
        this.user     = user;
        this.password = password;
    }

    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(user, password.toCharArray());
    }
}

selenium-java

selenium-java(IP白名单,推荐)

使用提示

  1. 基于白名单方式使用selenium-java认证代理
  2. 下载chromedriver(注意chromedriver版本要和Chrome版本对应)
  3. 依赖下载:selenium-java-4.1.2
  4. 请注意替换代码中的部分信息:
    ${tunnelhost:tunnelport}:隧道域名:端口号,如:"tpsXXX.XXX.com:15818"
    ${chromedriver_path}:您本机chromedriver驱动存放路径,如:"C:\chromedriver.exe"

                            
selenium-java(用户名密码认证)

使用提示

  1. 基于用户名密码方式使用selenium-java认证代理,仅支持图形化界面
  2. 下载chromedriver(注意chromedriver版本要和Chrome版本对应)
  3. 依赖下载:selenium-java-4.1.2
  4. 请注意替换代码中的部分信息:
    ${tunnelhost}:隧道域名,如:"tpsXXX.XXX.com"
    ${tunnelport}:隧道端口号,如:"15818"
    ${username}:用户名
    ${password}:密码
    ${chromedriver_path}:您本机chromedriver驱动存放路径,如:"C:\chromedriver.exe"

                            

resttemplate

RestTemplate

使用提示

  1. 此样例同时支持访问http和https网页
  2. 使用用户名密码访问的情况下,每次请求httpclient会发送两次进行认证从而导致请求耗时增加,建议使用白名单访问
  3. 依赖包下载:
    httpclient-4.5.13
    httpcore-4.4.13
    commons-codec-1.11
    commons-logging-1.2
    spring-web-5.3.9
    spring-beans-5.3.9
    spring-core-5.3.9
    spring-jcl-5.3.9
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.ProxyAuthenticationStrategy;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
public class ResTempTunnel {

        // 目标网站
        private static String pageUrl = "http://www.xx.com";
        // 隧道域名、端口号
        private static String proxyHost = "隧道域名";
        private static Integer proxyPort = 端口号;
        // 用户名密码, 若已添加白名单则不需要添加
        private static String ProxyUser = "name";
        private static String Proxypass = "password";

        public static void main(String[] args) {
            CredentialsProvider credsProvider = new BasicCredentialsProvider();
            credsProvider.setCredentials(
                    new AuthScope(proxyHost, proxyPort),
                    new UsernamePasswordCredentials(ProxyUser, Proxypass)
            );

            HttpHost proxy = new HttpHost(proxyHost, proxyPort);
            HttpClientBuilder clientBuilder = HttpClientBuilder.create();
            clientBuilder.useSystemProperties();
            clientBuilder.setProxy(proxy);
            clientBuilder.setDefaultCredentialsProvider(credsProvider);
            clientBuilder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy());

            CloseableHttpClient client = clientBuilder.build();
            HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
            factory.setHttpClient(client);

            RestTemplate restTemplate = new RestTemplate();
            restTemplate.setRequestFactory(factory);
            String result = restTemplate.getForObject(pageUrl, String.class);
            System.out.println(result);
        }

}

playwright

playwright

使用提示

  1. 基于白名单方式使用playwright认证代理
  2. 添加pom.xml依赖: playwright-1.35.0
  3. 请注意替换代码中的部分信息:
    ${ip:port}:隧道域名:端口号
import com.microsoft.playwright.*;

public class PlayWright {
    // 目标网站
    private static String pageUrl = "http://www.xx.com";
    // 添加白名单(隧道代理)
    private static String tunnelHost = "隧道域名";
    private static int  tunnelPort = 端口号;
    public static void main(String[] args) {

        try (Playwright playwright = Playwright.create()) {
            Browser browser = playwright.firefox().launch();
            BrowserContext context = browser.newContext(new Browser.NewContextOptions().setProxy(String.format("http://%s:%s", tunnelHost, tunnelPort)));
            Page page = context.newPage();
            Response response = page.navigate(pageUrl);
            System.out.println(response.text());
        }
    }
}

GoLang

标准库

标准库

使用提示

  1. http和https网页均可适用
  2. 建议关闭HTTP协议的keep-alive功能,避免因连接复用导致隧道不能切换IP。
package main

import (
	"compress/gzip"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
)

// 请求隧道服务器
// http和https网页均适用

func main() {
	// 用户名密码, 若已添加白名单则不需要添加
	username := "username"
	password := "password"

	// 隧道服务器
	proxy_raw := "隧道地址:端口号"
	//proxy_str := fmt.Sprintf("http://%s:%s@%s", nil, nil, proxy_raw)
	proxy_str := fmt.Sprintf("http://%s:%s@%s", username, password, proxy_raw)
	proxy, err := url.Parse(proxy_str)

	// 目标网页
	page_url := "http://www.xx.com"

	//  请求目标网页
	client := &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxy)}}
	req, _ := http.NewRequest("GET", page_url, nil)
	req.Header.Add("Accept-Encoding", "gzip")
	res, err := client.Do(req)

	if err != nil {
		// 请求发生异常
		fmt.Println(err.Error())
	} else {
		defer res.Body.Close()

		fmt.Println("status code:", res.StatusCode)

		// 解压缩读取返回内容
		if res.Header.Get("Content-Encoding") == "gzip" {
			reader, _ := gzip.NewReader(res.Body)
			defer reader.Close()
			io.Copy(os.Stdout, reader)
			os.Exit(0) // 正常退出
		}

		// 无压缩读取返回内容
		body, _ := ioutil.ReadAll(res.Body)
		fmt.Println(string(body))
	}
}                         

CSharp

标准库

标准库

使用提示

  1. http和https网页均可适用
  2. HttpWebRequest 在使用隧道代理可能会出现复用之前建立的连接导致不能正常更换IP,可在创建 HttpWebRequest对象后,使用 request.KeepAlive = false
using System.Net;
using System.Text;

namespace Sample
{
    internal class Program
    {

        static void Main(string[] args)
        {
            //隧道代理
            HTTPTunnelTest();
            Console.ReadKey();
        }
        static void HTTPTunnelTest()
        {
            // 目标网页
            string page_url = "http://www.xx.com";

            // 构造请求
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(page_url);
            request.Method = "GET";
            // 出现复用IP时使用
            //request.KeepAlive = false;  

            // 隧道域名端口号
            string tunnelhost = "隧道域名";
            int tunnelport = 端口号;

            // 用户名密码, 若已添加白名单则不需要添加
            string username = "username";
            string password = "password.";

            // 设置代理 白名单
            //request.Proxy = new WebProxy(tunnelhost, tunnelport);

            // 设置代理 用户名密码
            WebProxy proxy = new WebProxy();
            proxy.Address = new Uri(String.Format("http://{0}:{1}", tunnelhost, tunnelport));
            proxy.Credentials = new NetworkCredential(username, password);
            request.Proxy = proxy;

            // 请求目标网页
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            // 获取状态码
            Console.WriteLine((int)response.StatusCode);  

            StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
    
            Console.WriteLine(reader.ReadToEnd());
            
        }
    }
}

Node.js

标准库(http+url)

标准库(http,https均适用)

使用提示

  1. http,https均适用
  2. 建议关闭HTTP协议的keep-alive功能,避免因连接复用导致隧道不能切换IP。
const http = require("http");  // 引入内置http模块
const url = require("url");

// 要访问的目标页面
const targetUrl = "http://www.xx.com";
const urlParsed = url.parse(targetUrl);

// 隧道域名
const proxyIp = "隧道服务器域名";
const proxyPort = "端口号";

// 用户名密码, 若已添加白名单则不需要添加
//const username = "username";
//const password = "password";

//const base64 = new Buffer.from(username + ":" + password).toString("base64");
const options = {
    host: proxyIp,
    port: proxyPort,
    path: targetUrl,
    method: "GET",
    headers: {
        "Host": urlParsed.hostname,
        //"Proxy-Authorization": "Basic " + base64
    }
};

http.request(options, (res) => {
    console.log("got response: " + res.statusCode);
    // 输出返回内容(使用了gzip压缩)
    if (res.headers['content-encoding'] && res.headers['content-encoding'].indexOf('gzip') != -1) {
        let zlib = require('zlib');
        let unzip = zlib.createGunzip();
        res.pipe(unzip).pipe(process.stdout);
    } else {
        // 输出返回内容(未使用gzip压缩)
        res.pipe(process.stdout);
    }
})
    .on("error", (err) => {
        console.log(err);
    })
    .end()
    ;

标准库(http+tls+util)

标准库(适用http和https请求)

使用提示

  1. http网页和https网页均可适用
let http = require('http'); // 引入内置http模块
let tls = require('tls'); // 引入内置tls模块
let util = require('util');

// 用户名密码认证(白名单方式可注释)
const username = 'username';
const password = 'password';
const auth = 'Basic ' + Buffer.from(username + ':' + password).toString('base64');

// 代理服务器ip和端口
let proxy_ip = 'tunnelhost';
let proxy_port = port;

// 要访问的主机和路径
let remote_host = 'www.xx.com';
let remote_path = '/';


// 发起CONNECT请求
let req = http.request({
    host: proxy_ip,
    port: proxy_port,
    method: 'CONNECT',
    path: remote_host,
    headers: {
        "Host": remote_host,
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36",
        "Proxy-Authorization": auth,
        "Accept-Encoding": "gzip"   // 使用gzip压缩让数据传输更快
    },
    rejectUnauthorized: false
});

req.on('connect', function (res, socket, head) {
    console.log('状态码:', res.statusCode);
    // TLS握手
    let tlsConnection = tls.connect({
        host: remote_host,
        socket: socket
    }, function () {
        // 发起GET请求
        tlsConnection.write(util.format('GET %s HTTP/1.1\r\nHost: %s\r\n\r\n', remote_path, remote_host));
    });

    tlsConnection.on('data', function (data) {
        // 输出响应结果(完整的响应报文串)
        console.log(data.toString());
    });
});

req.end();

request

request

使用提示

  1. 请先安装request库: npm install request
  2. http网页和https网页均可适用
let request = require('request'); // 引入第三方request库
let util = require('util');
let zlib = require('zlib');

// 用户名密码, 若已添加白名单则不需要添加
//const username = 'username';
//const password = 'password';

// 要访问的目标地址
let page_url = 'http://www.xx.com'

// 隧道服务器域名和端口
let tunnelhost = '隧道服务器域名';
let tunnelport = 端口;

// 用户名密码完整隧道服务器url
//let proxy = util.format('http://%s:%s@%s:%d', username, password, tunnelhost, tunnelport);
//// 白名单完整隧道服务器url
let proxy = util.format('http://%s:%d', tunnelhost, tunnelport);

// 发起请求
request({
    url: page_url,
    method: 'GET',
    proxy: proxy,
    headers: {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36",
        "Accept-Encoding": "gzip"   // 使用gzip压缩让数据传输更快
    },
    encoding: null,  // 方便解压缩返回的数据
}, function (error, res, body) {
    if (!error && res.statusCode == 200) {
        // 输出返回内容(使用了gzip压缩)
        if (res.headers['content-encoding'] && res.headers['content-encoding'].indexOf('gzip') != -1) {
            zlib.gunzip(body, function (err, dezipped) {
                console.log(dezipped.toString());
            });
        } else {
            // 输出返回内容(没有使用gzip压缩)
            console.log(body);
        }
    } else {
        console.log(error);
    }
});

puppeteer(IP白名单|用户名密码)

puppeteer

使用提示

  1. 基于IP白名单|用户名密码的http/https代理Puppeteer
  2. 运行环境要求: node7.6.0或以上 + puppeteer
  3. 请先安装puppeteer: npm i puppeteer
// 引入puppeteer模块
const puppeteer = require('puppeteer');

// 要访问的目标网页
const url = 'http://www.xx.com';

// 添加headers
const headers = {
    'Accept-Encoding': 'gzip' // 使用gzip压缩让数据传输更快
};
// 用户名密码方式 (若白名单方式,注释下行并提前设置白名单)
const username = 'username';
const password = 'password';

(async () => {
    // 新建一个浏览器实例
    const browser = await puppeteer.launch({
        headless: false,  // 是否不显示窗口, 默认为true, 设为false便于调试
        args: [
            '--proxy-server=tunnelHost:port',
            '--no-sandbox',
            '--disable-setuid-sandbox'
        ],
        executablePath: "C:\\chrome.exe"
    });

    // 打开一个新页面
    const page = await browser.newPage();

    // 设置headers
    await page.setExtraHTTPHeaders(headers);

    // 用户民密码认证
    await page.authenticate({ username: username, password: password });

    // 访问目标网页
    await page.goto(url);

})();

axios

axios

使用提示

  • 请先安装axioshttps-proxy-agent库: npm install axios https-proxy-agent
const axios = require('axios');
const { HttpsProxyAgent } = require("https-proxy-agent");

// 代理隧道域名和端口
let tunnelHost = '代理隧道域名'
let tunnelPort = '端口'

// 配置用户名和密码
let username = 'username'
let password = 'password.'

axios({
    url: 'http://www.xx.com',
    method: "get",
    httpAgent: new HttpsProxyAgent(`http://${username}:${password}@${tunnelHost}:${tunnelPort}`),
    httpsAgent: new HttpsProxyAgent(`http://${username}:${password}@${tunnelHost}:${tunnelPort}`),
}).then(
    res => {
        console.log(res.data);
    }
).catch(err => {
    console.log(err);
})

websocket

websocket

使用提示

  • 请先安装wshttps-proxy-agent库: npm install ws https-proxy-agent
const WebSocket = require('ws');
const { HttpsProxyAgent } = require("https-proxy-agent");

// 代理隧道域名和端口
let tunnelHost = '代理隧道域名'
let tunnelPort = '端口'

// 配置用户名和密码
let username = 'username'
let password = 'password'

const target = 'ws://echo.websocket.events/';
const agent = new HttpsProxyAgent(`http://${username}:${password}@${tunnelHost}:${tunnelPort}`);
//const agent = new HttpsProxyAgent(`http://${tunnelHost}:${tunnelPort}`);
const socket = new WebSocket(target, { agent });

socket.on('open', function() {
    console.log('"open" event!');
    socket.send('hello world');
});

socket.on('message', function(data, flags) {
    console.log('"message" event!', data, flags);
    socket.close();
});

Ruby

net/http

net/http(IP白名单)

使用提示

  1. 基于ip白名单的http/https代理net/http
  2. 建议关闭HTTP协议的keep-alive功能,避免因连接复用导致隧道不能切换IP。

                            
net/http(用户名密码认证)

使用提示

  1. 基于用户名密码认证的http/https代理net/http

                            

httparty

httparty(IP白名单)

使用提示

  1. 基于IP白名单认证的http/https代理httparty

                            
httparty(用户名密码认证)

使用提示

  1. 基于用户名密码认证的http/https代理httparty


php

curl

curl

使用提示

  1. 此样例同时支持访问http和https网页
  2. curl不是php原生库,需要安装才能使用:
    Ubuntu/Debian系统:apt-get install php5-curl
    CentOS系统:yum install php-curl
  3. 建议关闭HTTP协议的keep-alive功能,避免因连接复用导致隧道不能切换IP。
/**
 * 使用cURL通过HTTP隧道代理访问HTTPS网站
 * 适用于需要通过代理访问HTTPS资源的场景
 */

// 目标网站(HTTPS)
$targetUrl = 'https://www.xx.com';

// 代理服务器信息
$proxyHost = 'ip';  // 代理IP
$proxyPort = port;         // 代理端口
$proxyUser = '';           // 代理用户名(可选)
$proxyPass = '';           // 代理密码(可选)

// 初始化cURL
$ch = curl_init();

// 设置目标URL
curl_setopt($ch, CURLOPT_URL, $targetUrl);

// 设置代理服务器
curl_setopt($ch, CURLOPT_PROXY, $proxyHost);
curl_setopt($ch, CURLOPT_PROXYPORT, $proxyPort);

// 设置代理类型为HTTP(支持隧道)
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);

// 如果代理需要认证
if (!empty($proxyUser) && !empty($proxyPass)) {
    curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$proxyUser}:{$proxyPass}");
}

// 关键:允许cURL使用隧道连接HTTPS(自动处理CONNECT方法)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);  // 开发环境可关闭证书验证
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);  // 生产环境建议开启并配置CA证书

// 设置其他选项
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);   // 将响应以字符串返回而非直接输出
curl_setopt($ch, CURLOPT_HEADER, true);           // 包含响应头信息
curl_setopt($ch, CURLOPT_TIMEOUT, 30);            // 超时时间(秒)
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);     // 连接超时时间(秒)

// 执行请求
$response = curl_exec($ch);

// 处理结果
if ($response === false) {
    // 请求失败,输出错误信息
    echo "请求失败:" . curl_error($ch);
} else {
    // 分离响应头和响应体
    $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $headers = substr($response, 0, $headerSize);
    $body = substr($response, $headerSize);
    
    echo "===== 响应头 =====" . PHP_EOL;
    echo $headers . PHP_EOL;
    echo "===== 响应体 =====" . PHP_EOL;
    echo $body . PHP_EOL;
}

// 获取请求信息(可选)
$info = curl_getinfo($ch);
echo PHP_EOL . "===== 请求信息 =====" . PHP_EOL;
echo "HTTP状态码:" . $info['http_code'] . PHP_EOL;
echo "总耗时:" . $info['total_time'] . "秒" . PHP_EOL;

// 关闭cURL资源
curl_close($ch);

易语言

易语言使用代理

使用提示

  1. 需要用到两个模块:精易模块和鱼刺类
  2. 隧道代理请将IP端口更改为隧道域名端口即可
.支持库 精易模块
.支持库 spec

.程序集 窗口程序集_启动窗口

.子程序 _按钮_访问_被单击
.局部变量 代理配置, 网络配置
.局部变量 访问结果, 文本型

' 配置代理信息
代理配置.代理类型 = 1  ' 1=HTTP代理(支持隧道)
代理配置.代理地址 = 编辑框_代理IP.内容 + “:” + 编辑框_代理端口.内容
代理配置.代理用户 = 编辑框_用户名.内容
代理配置.代理密码 = 编辑框_密码.内容

' 访问HTTPS网站(精易模块会自动处理CONNECT隧道)
访问结果 = 网页_访问S (“https://www.xx.com”, , , , , , 代理配置)

.如果 (访问结果 ≠ “”)
    编辑框_结果.内容 = 访问结果
    信息框 (“隧道代理访问成功”, 0, )
.否则
    信息框 (“访问失败,错误码:” + 到文本 (网页_取错误代码 ()), 0, “错误”)
.如果结束

.子程序 _启动窗口_创建完毕
编辑框_代理IP.提示文本 = “代理服务器IP”
编辑框_代理端口.提示文本 = “代理端口(如8080)”
按钮_访问.标题 = “通过隧道代理访问目标网站HTTPS”