PHP cURL爬取特定网站遇连接超时(仅线上服务器),如何解决?
问题描述
我尝试用以下PHP cURL代码爬取特定网站HTML中的h1元素:
<?php error_reporting(E_ALL); ini_set('display_errors', 1); header('Content-Type: text/plain; charset=utf-8'); header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: POST, GET, OPTIONS'); if(isset($_POST["url"])){ $user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36"; $ch = curl_init(); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3600); curl_setopt($ch, CURLOPT_TIMEOUT, 3600); curl_setopt($ch, CURLOPT_USERAGENT, $user_agent); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_VERBOSE, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); $html=curl_exec($ch); if (!curl_errno($ch)){ $resultStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($resultStatus == 200) { @$DOM = new DOMDocument; @$DOM->loadHTML('<?xml encoding="UTF-8">' . $html); echo $DOM->getElementsByTagName('h1')[0]->textContent; } else echo "Error: ".$resultStatus; } else echo "No h1 found ".curl_error($ch) } ?>
目标网址:
https://neindiabroadcast.com/2023/03/24/bharat-gaurav-train-flagged-off-from-guwahati-for-arunachal-pradesh/
但持续收到错误:
No h1 found Failed to connect to neindiabroadcast.com port 443 after 15402 ms: Connection timed out
已将CURLOPT_CONNECTTIMEOUT和CURLOPT_TIMEOUT设置为3600秒,但问题仍存在。且仅线上服务器出现该错误,本地服务器可成功获取数据。
解决方案
1. 修复代码中的变量未定义问题
代码中未将$_POST["url"]赋值给$url变量,导致cURL请求的URL未定义,这是明显的逻辑错误。在if(isset($_POST["url"])){后添加如下代码:
$url = $_POST["url"];
2. 排查线上服务器IP是否被目标网站屏蔽
本地能正常访问但线上不行,大概率是线上服务器的IP被目标网站的反爬机制封禁。可以通过以下方式验证:
- 登录线上服务器,执行命令测试连接:
如果命令返回连接超时或拒绝,说明IP被屏蔽。curl -v https://neindiabroadcast.com # 或者用telnet测试端口连通性 telnet neindiabroadcast.com 443 - 解决办法:
- 使用代理IP中转请求,在cURL中添加代理配置:
curl_setopt($ch, CURLOPT_PROXY, 'http://your-proxy-ip:port'); // 如果代理需要认证 curl_setopt($ch, CURLOPT_PROXYUSERPWD, 'username:password'); - 联系服务器提供商更换服务器IP;
- 使用CDN或云函数中转请求,避免直接用服务器IP访问目标网站。
- 使用代理IP中转请求,在cURL中添加代理配置:
3. 优化cURL请求头,模拟真实浏览器
目标网站可能会识别非标准请求头并拦截。修改请求头,让请求更贴近真实浏览器:
- 将换行的User-Agent改为单行:
$user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36"; - 添加完整的HTTP请求头:
curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 'Accept-Language: en-US,en;q=0.5', 'Referer: https://neindiabroadcast.com/', 'DNT: 1', 'Connection: keep-alive', 'Upgrade-Insecure-Requests: 1' ));
4. 检查线上服务器的网络限制
部分服务器提供商可能会限制出站的HTTPS请求,或服务器防火墙规则拦截了对目标网站的访问:
- 测试线上服务器能否访问其他HTTPS网站(如
curl https://google.com),如果也失败,联系服务器提供商排查网络权限; - 检查服务器的防火墙配置,确保允许访问目标网站的443端口。
5. 调整cURL的SSL配置
线上服务器的SSL环境可能与本地不同,尝试指定TLS版本并调整验证设置:
// 指定TLS版本(根据目标网站支持的版本选择,通常TLSv1.2或TLSv1.3) curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); // 开启SSL主机验证(如果IP未被封,严格验证可避免部分SSL错误) curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
内容的提问来源于stack exchange,提问作者user21506970
相关产品推荐
相关产品推荐

