最近,我开始遇到一段稳定了很长一段时间的代码的问题。它连接到GameStop以在那里检索页面。多年来一直表现良好,但现在又暂停了。
起初,我认为其中涉及某种IP或用户代理阻塞。然而,我在DigitalOcean和Vultr上都开发了全新的机器,两者都遇到了同样的问题。尽管如此,所有的机器都可以通过命令行使用cURL,并可以很好地检索页面。
奇怪的是,这些代码也可以在我的本地开发机器上运行,那是一个Windows盒子。所以,不确定是否存在和运行在Linux上的PHP有关的问题?
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'https://www.gamestop.com/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
//curl_setopt($ch, CURLOPT_SSLVERSION, 6); -explicitly use TLS v1.2
$html = curl_exec($ch);
$info = curl_getinfo($ch);
$error = curl_error($ch);
curl_close($ch);
echo '<pre>' . var_export($error, true) . '</pre>'
. '<pre>' . var_export($info, true) . '</pre>'
. 'HTML: <textarea>' . $html . '</textarea>';
?>
上面的代码在我尝试运行它的任何非本地环境中都会返回超时。在相同的环境中,可以通过命令行使用cURL获取页面。我发现了一些类似的问题,但大多数都指向SSL/TLS版本的问题。我也尝试过对此进行测试(见注释行),但结果相同。
问题的一部分是,我不确定是否有真正的方法来调试来自服务器的超时,因为实际上任何事情都可能导致超时。我得到的唯一真正线索是,它在Windows机器上工作,在更高的环境中在命令行上工作。如有任何帮助或见解,我们将不胜感激!
编辑:还能够在Windows Server 2016虚拟机上重现该问题。
很可能是因为curl-cli自动添加了一个用户代理头,而libcurl/php没有。
涉及某种IP或用户代理阻塞。然而,我在DigitalOcean和Vultr上都开发了全新的机器,并且都遇到了相同的问题
在DigitalOcean/Vultr上设置VM不会自动使libcurl向您的https请求添加用户代理标头。可以使用
curl_setop($ch,CURLOPT_USERAGENT,"curl/".(curl_version()["version"])); // User-Agent: curl/7.52.1
模仿curl-cli的用户代理字符串,或者类似的东西
curl_setopt($ch,CURLOPT_USERAGENT,"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36");
假装你是运行在Windows7x64上的谷歌Chrome 71版。
许多网站(例如,Wikipedia.com)会阻止缺少用户代理标头的http请求。
虽然它并没有真正解释为什么会发生,但我通过在PHP中使用shell_exec直接执行命令行cURL,然后检索/处理结果,解决了这个问题。