接入指南
PHP cURL 代理设置教程(含 Guzzle)
PHP 的 cURL 扩展把代理地址和登录信息分成两个选项,密码里有特殊字符也不会弄坏地址。Guzzle 基于同一个扩展,但要的是一个完整的代理 URL。两种写法下面都有,最后还有一个把请求依次交给多个静态 IP 的循环。
开始之前
- 启用了 curl 扩展的 PHP 8。Debian 和 Ubuntu 把它单独打包,包名带 PHP 版本号,例如 php8.3-curl。
- Guzzle 示例需要 Composer:composer require guzzlehttp/guzzle。
- 控制台服务页面上的 HOST、PORT、USERNAME 和 PASSWORD。
你的连接信息
登录控制台,打开你购买的服务。服务页面上会显示该服务的主机、端口、用户名和密码。ProxyPanda 没有一个统一的固定地址,所以每次都请从那里复制。指南中的代码使用下面这些占位符,请逐一替换成你自己的值。
- HOST
- 该服务的代理地址,按服务页面上显示的原样填写。
- PORT
- 要连接的端口。请和主机一起复制,因为不同服务的端口可能不同。
- USERNAME
- 你的代理登录名。它与你登录控制台所用的邮箱是分开的。
- PASSWORD
- 请完整复制。住宅代理在控制台中选择的选项会附加在密码末尾,凭记忆手动输入的密码会丢失这些选项。
把你用来连接的 IP 地址加入服务的白名单,就可以不用用户名和密码。这时代码里只需要 HOST 和 PORT。
示例都使用 HTTP,它可以通过加密隧道访问 https 网站。SOCKS5 同样可用:住宅代理的端口两种都接受,ISP 和数据中心代理在控制台里切换协议。
步骤
确认 curl 扩展已经加载
php -m 会列出所有已加载的扩展。列表里没有 curl 时,为你的 PHP 安装对应的软件包,或在 php.ini 里取消 extension=curl 的注释,然后再看一次。
terminal php -m | grep -i curl让 cURL 句柄指向代理
CURLOPT_PROXY 填 http://HOST:PORT,CURLOPT_PROXYUSERPWD 填 USERNAME:PASSWORD。两个超时分别限制连上代理的等待时间和整次传输的最长时间。脚本会输出 api.ipify.org 看到的地址。
check_ip.php <?php $ch = curl_init('https://api.ipify.org?format=json'); curl_setopt_array($ch, [ CURLOPT_PROXY => 'http://HOST:PORT', CURLOPT_PROXYUSERPWD => 'USERNAME:PASSWORD', CURLOPT_RETURNTRANSFER => true, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 30, ]); $body = curl_exec($ch); if ($body === false) { echo 'cURL error ', curl_errno($ch), ': ', curl_error($ch), PHP_EOL; } else { echo $body, PHP_EOL; }弄清 CURLOPT_HTTPPROXYTUNNEL 何时有用
访问 https 网址时,cURL 会自己经代理建立 CONNECT 隧道,网站的 TLS 端到端保持加密,这个选项不起作用。设为 true 后,普通 http 网址也会强制走隧道。不设置时,这类请求以普通 HTTP 交给代理,大多数任务这样就够了。
用 Guzzle 发同样的请求
Guzzle 读取一个带登录信息的代理 URL,connect_timeout 和 timeout 对应 cURL 的两个超时。密码里含有 @、: 或 / 时,先用 rawurlencode 处理,再拼进 URL。
guzzle.php <?php require __DIR__ . '/vendor/autoload.php'; use GuzzleHttp\Client; $client = new Client([ 'proxy' => 'http://USERNAME:PASSWORD@HOST:PORT', 'connect_timeout' => 10, 'timeout' => 30, ]); $response = $client->get('https://api.ipify.org?format=json'); echo $response->getBody(), PHP_EOL;在多个静态 IP 之间轮流使用
ISP 和数据中心服务租给你的是一组固定地址。把它们存进 proxies.txt,每行一个,格式为 HOST:PORT:USERNAME:PASSWORD,循环会把每个请求交给下一行。把示例里重复的 ipify 网址换成你要抓取的页面。
rotate.php <?php $proxies = file('proxies.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); $urls = array_fill(0, 6, 'https://api.ipify.org'); foreach ($urls as $i => $url) { [$host, $port, $user, $pass] = explode(':', trim($proxies[$i % count($proxies)]), 4); $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_PROXY => "$host:$port", CURLOPT_PROXYUSERPWD => "$user:$pass", CURLOPT_RETURNTRANSFER => true, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 30, ]); $body = curl_exec($ch); echo $host, ' -> ', $body === false ? curl_error($ch) : $body, PHP_EOL; }
轮换 IP 与粘性 IP
每次 curl_init 都会创建新的句柄和新的连接。住宅代理选“随机 IP”时,第一个脚本运行两次会打印两个不同的地址。
复用同一个句柄或同一个 Guzzle 客户端,连接会在多次调用之间保持,共用连接的请求从同一个地址发出。这适合“粘性 IP”和静态 IP;在“随机 IP”模式下想换出口,就新建一个句柄。
轮换循环是为静态产品线准备的,proxies.txt 的每一行都是不同的固定 IP。住宅代理在代理端轮换,只写一行并选“随机 IP”就能达到同样效果。
常见错误与解决办法
Call to undefined function curl_init()
运行脚本的 PHP 没有加载 curl 扩展。命令行 PHP 和 Web 服务器里的 PHP 可能读取不同的 php.ini;php --ini 会显示命令行用的是哪一个。
cURL error 56: CONNECT tunnel failed, response 407
代理拒绝了登录。重新复制 USERNAME 和 PASSWORD。在 Guzzle 中用 rawurlencode 编码特殊字符,或者改用原生 cURL,CURLOPT_PROXYUSERPWD 里的密码不需要编码。
cURL error 7: Failed to connect
那个主机和端口上没有代理应答。把两者和服务页面对照一遍,再到控制台确认服务没有到期。
cURL error 28: Operation timed out
传输超过了 CURLOPT_TIMEOUT。住宅出口是家庭网络,有时较慢,可以多给一些时间,并只重试这一个网址,不必整批重来。
cURL error 60: SSL certificate problem: unable to get local issuer certificate
PHP 找不到 CA 证书包,Windows 版 PHP 上最常见。在 php.ini 中把 curl.cainfo 指向一个较新的 cacert.pem。关闭证书校验只是把问题藏起来,并不是解决办法。
其他接入指南
有不明白的词? 术语表用大白话解释。
卡在某一步了?
把命令和报错贴到 Discord,记得先删掉密码。那里的人大多遇到过这些错误。