Python API代理示例
Python(API代理)
流程:提取 API 链接 → 解析 JSON → 处理错误码 → 使用返回的代理访问目标站。
请将 apiUrl 替换为您自己的 API 提取链接。
requests
1import requests234apiUrl = "http://ip.16yun.cn:817/myip/pl/<ORDER_ID>/?s=<ORDER_SIGN>&u=<USER>&format=json"56def fetch_proxy_from_api():7try:8resp = requests.get(apiUrl, timeout=10)9except requests.RequestException as e:10raise SystemExit(f"API 请求失败: {e}")1112if resp.status_code != 200:13if resp.status_code == 400:14raise SystemExit("API错误 400: 参数错误")15if resp.status_code == 403:16raise SystemExit("API错误 403: 主机IP不在白名单")17if resp.status_code == 429:18raise SystemExit("API错误 429: 提取频率过快")19raise SystemExit(f"API错误 {resp.status_code}")2021data = resp.json()22if not isinstance(data, list) or len(data) == 0:23raise SystemExit("API 返回为空或格式异常")24first = data[0]25ip = first.get("ip")26port = first.get("port")27if not ip or not port:28raise SystemExit("API 返回缺少 ip/port 字段")29return ip, port3031def visit_target_with_proxy(ip, port):32proxies = {33"http": f"http://{ip}:{port}",34"https": f"http://{ip}:{port}",35}36try:37r = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=10)38r.raise_for_status()39except requests.RequestException as e:40raise SystemExit(f"访问目标站失败: {e}")41print(r.text)4243if __name__ == "__main__":44ip, port = fetch_proxy_from_api()45visit_target_with_proxy(ip, port)
httpx(同步/异步)
1import httpx2import asyncio34apiUrl = "http://ip.16yun.cn:817/myip/pl/<ORDER_ID>/?s=<ORDER_SIGN>&u=<USER>&format=json"56def fetch_proxy_sync():7try:8r = httpx.get(apiUrl, timeout=10)9except httpx.HTTPError as e:10raise SystemExit(f"API 请求失败: {e}")11if r.status_code != 200:12mapping = {400:"参数错误",403:"主机IP不在白名单",429:"提取频率过快"}13raise SystemExit(f"API错误 {r.status_code}: {mapping.get(r.status_code, '未知错误')}")14arr = r.json()15if not arr:16raise SystemExit("API 返回为空")17return arr[0]["ip"], arr[0]["port"]1819async def fetch_proxy_async():20async with httpx.AsyncClient(timeout=10) as client:21r = await client.get(apiUrl)22if r.status_code != 200:23raise SystemExit(f"API错误 {r.status_code}")24arr = r.json()25return arr[0]["ip"], arr[0]["port"]2627def visit_with_httpx(ip, port):28proxies = {29"http://": f"http://{ip}:{port}",30"https://": f"http://{ip}:{port}",31}32r = httpx.get("https://httpbin.org/ip", proxies=proxies, timeout=10)33print(r.text)3435if __name__ == "__main__":36ip, port = fetch_proxy_sync()37visit_with_httpx(ip, port)38# 或使用异步39# ip, port = asyncio.run(fetch_proxy_async())40# visit_with_httpx(ip, port)
aiohttp
1import aiohttp2import asyncio34apiUrl = "http://ip.16yun.cn:817/myip/pl/<ORDER_ID>/?s=<ORDER_SIGN>&u=<USER>&format=json"56async def main():7async with aiohttp.ClientSession() as session:8async with session.get(apiUrl, timeout=10) as resp:9if resp.status != 200:10raise SystemExit(f"API错误 {resp.status}")11arr = await resp.json()12if not arr:13raise SystemExit("API 返回为空")14ip, port = arr[0]["ip"], arr[0]["port"]1516proxy = f"http://{ip}:{port}"17async with aiohttp.ClientSession() as session:18async with session.get("https://httpbin.org/ip", proxy=proxy, timeout=10) as r:19print(await r.text())2021if __name__ == "__main__":22asyncio.run(main())
urllib.request(urllib2)
1import json2from urllib import request, error34apiUrl = "http://ip.16yun.cn:817/myip/pl/<ORDER_ID>/?s=<ORDER_SIGN>&u=<USER>&format=json"56def fetch_proxy_from_api():7try:8with request.urlopen(apiUrl, timeout=10) as resp:9if resp.status != 200:10raise SystemExit(f"API错误 {resp.status}")11data = json.loads(resp.read().decode("utf-8"))12except error.URLError as e:13raise SystemExit(f"API 请求失败: {e}")1415if not isinstance(data, list) or not data:16raise SystemExit("API 返回为空或格式异常")17first = data[0]18ip = first.get("ip")19port = first.get("port")20if not ip or not port:21raise SystemExit("API 返回缺少 ip/port 字段")22return ip, port2324def visit_with_urllib(ip, port):25proxy_handler = request.ProxyHandler({26"http": f"http://{ip}:{port}",27"https": f"http://{ip}:{port}",28})29opener = request.build_opener(proxy_handler)30opener.addheaders = [("User-Agent", "Mozilla/5.0")]31with opener.open("https://httpbin.org/ip", timeout=10) as r:32print(r.read().decode("utf-8"))3334if __name__ == "__main__":35ip, port = fetch_proxy_from_api()36visit_with_urllib(ip, port)
Python 2(如仍在使用)对应
urllib2:1# -*- coding: utf-8 -*-2import json3import urllib245apiUrl = "http://ip.16yun.cn:817/myip/pl/<ORDER_ID>/?s=<ORDER_SIGN>&u=<USER>&format=json"67def fetch_proxy_from_api():8r = urllib2.urlopen(apiUrl, timeout=10)9data = json.loads(r.read())10ip, port = data[0]["ip"], data[0]["port"]11return ip, port1213def visit_with_urllib2(ip, port):14proxy_handler = urllib2.ProxyHandler({15"http": "http://%s:%s" % (ip, port),16"https": "http://%s:%s" % (ip, port),17})18opener = urllib2.build_opener(proxy_handler)19opener.addheaders = [("User-Agent", "Mozilla/5.0")]20r = opener.open("https://httpbin.org/ip", timeout=10)21print r.read()2223if __name__ == "__main__":24ip, port = fetch_proxy_from_api()25visit_with_urllib2(ip, port)
Scrapy(Downloader Middleware)
在 Scrapy 中,推荐通过 Downloader Middleware 为请求动态设置代理。
middlewares.py:
12import time3import json4import logging5import requests67logger = logging.getLogger(__name__)89class ApiProxyMiddleware(object):10def __init__(self, api_url, cache_ttl_seconds=30):11self.api_url = api_url12self.cache_ttl_seconds = cache_ttl_seconds13self._cached_proxy = None14self._cached_at = 0.01516@classmethod17def from_crawler(cls, crawler):18api_url = crawler.settings.get(19"API_PROXY_URL",20"http://ip.16yun.cn:817/myip/pl/<ORDER_ID>/?s=<ORDER_SIGN>&u=<USER>&format=json",21)22ttl = crawler.settings.getint("API_PROXY_CACHE_TTL", 30)23return cls(api_url, ttl)2425def _need_refresh(self):26return (time.time() - self._cached_at) >= self.cache_ttl_seconds or not self._cached_proxy2728def _fetch_proxy(self):29r = requests.get(self.api_url, timeout=10)30if r.status_code != 200:31raise RuntimeError("API错误 {}".format(r.status_code))32arr = r.json()33if not arr:34raise RuntimeError("API 返回为空")35first = arr[0]36ip, port = first.get("ip"), first.get("port")37if not ip or not port:38raise RuntimeError("API 返回缺少 ip/port")39return "http://{}:{}".format(ip, port)4041def process_request(self, request, spider):42try:43if self._need_refresh():44self._cached_proxy = self._fetch_proxy()45self._cached_at = time.time()46request.meta["proxy"] = self._cached_proxy47except Exception as e:48logger.warning("设置代理失败: %s", e)49# 放行请求(不加代理)或根据需要抛出异常50# raise
settings.py:
12HTTPPROXY_ENABLED = True345API_PROXY_URL = "http://ip.16yun.cn:817/myip/pl/<ORDER_ID>/?s=<ORDER_SIGN>&u=<USER>&format=json"6API_PROXY_CACHE_TTL = 3078DOWNLOADER_MIDDLEWARES = {9# 确保在默认代理中间件之前或之后,依据你的项目来放置10'your_project.middlewares.ApiProxyMiddleware': 543,11}
example_spider.py:
1import scrapy23class HttpBinSpider(scrapy.Spider):4name = "httpbin"5start_urls = ["https://httpbin.org/ip"]67def parse(self, response):8self.logger.info("响应: %s", response.text)
urllib3
1import json2import urllib334apiUrl = "http://ip.16yun.cn:817/myip/pl/<ORDER_ID>/?s=<ORDER_SIGN>&u=<USER>&format=json"56def fetch_proxy_from_api():7http = urllib3.PoolManager(timeout=urllib3.Timeout(connect=5.0, read=10.0))8r = http.request("GET", apiUrl)9if r.status != 200:10raise SystemExit("API错误 {}".format(r.status))11arr = json.loads(r.data.decode("utf-8"))12ip, port = arr[0]["ip"], arr[0]["port"]13return ip, port1415def visit_with_urllib3(ip, port):16proxy_url = f"http://{ip}:{port}"17http = urllib3.ProxyManager(proxy_url, timeout=urllib3.Timeout(connect=5.0, read=10.0))18r = http.request("GET", "https://httpbin.org/ip", headers={"User-Agent": "Mozilla/5.0"})19print(r.data.decode("utf-8"))2021if __name__ == "__main__":22ip, port = fetch_proxy_from_api()23visit_with_urllib3(ip, port)
Selenium(Chrome 示例)
1import requests2from selenium import webdriver3from selenium.webdriver.chrome.options import Options45apiUrl = "http://ip.16yun.cn:817/myip/pl/<ORDER_ID>/?s=<ORDER_SIGN>&u=<USER>&format=json"67def fetch_proxy():8r = requests.get(apiUrl, timeout=10)9r.raise_for_status()10arr = r.json()11return arr[0]["ip"], arr[0]["port"]1213if __name__ == "__main__":14ip, port = fetch_proxy()15options = Options()16options.add_argument(f"--proxy-server=http://{ip}:{port}")17driver = webdriver.Chrome(options=options)18try:19driver.get("https://httpbin.org/ip")20print(driver.page_source)21finally:22driver.quit()
Playwright(同步 API)
1import requests2from playwright.sync_api import sync_playwright34apiUrl = "http://ip.16yun.cn:817/myip/pl/<ORDER_ID>/?s=<ORDER_SIGN>&u=<USER>&format=json"56def fetch_proxy():7r = requests.get(apiUrl, timeout=10)8r.raise_for_status()9arr = r.json()10return arr[0]["ip"], arr[0]["port"]1112if __name__ == "__main__":13ip, port = fetch_proxy()14with sync_playwright() as p:15browser = p.chromium.launch()16context = browser.new_context(proxy={"server": f"http://{ip}:{port}"})17page = context.new_page()18page.goto("https://httpbin.org/ip")19print(page.content())20browser.close()
curl_cffi(高性能请求库)
1from curl_cffi import requests as c_requests23apiUrl = "http://ip.16yun.cn:817/myip/pl/<ORDER_ID>/?s=<ORDER_SIGN>&u=<USER>&format=json"45def fetch_proxy():6arr = c_requests.get(apiUrl, timeout=10).json()7return arr[0]["ip"], arr[0]["port"]89if __name__ == "__main__":10ip, port = fetch_proxy()11proxies = {12"http": f"http://{ip}:{port}",13"https": f"http://{ip}:{port}",14}15r = c_requests.get("https://httpbin.org/ip", proxies=proxies, timeout=10)16print(r.text)