【问题标题】:PHP: How to get website with cURL and act like a real browser?PHP:如何使用 cURL 获取网站并像真正的浏览器一样工作?
【发布时间】:2020-02-26 22:06:05
【问题描述】:

我想使用 PHP cURL 获取特定网站的源代码。

用我的电脑上的浏览器访问这个网站没有任何问题。

但是当我想用我的 PHP 脚本访问这个网站时,网站会识别出这是一个自动请求并显示一条错误消息。

这是我的 PHP 脚本:

<?php
$url = "https://www.example.com";
$user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.1 Safari/605.1.15";
$header = array('http' => array('user_agent' => $user_agent));

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
curl_close($ch);
echo $data;
?>

用户代理与我在浏览器中使用的相同。我正在使用带有 MAMP PRO 的本地服务器。这意味着我对浏览器访问和 PHP 脚本访问都使用相同的 IP 地址。

我已经用许多不同的标题和选项尝试了我的 PHP 脚本,但没有任何效果。

对于我想要访问网站的 Web 服务器,必须有任何东西使 PHP 脚本访问看起来与浏览器访问不同。但是什么?你有什么想法吗?

编辑

我发现它可以使用这个 cURL:

curl 'https://www.example.com/' -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36' -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3' -H 'accept-language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7'

如果我输入这个,例如终端,它显示了正确的源代码。

我将其转换为 PHP 脚本如下:

<?php
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://www.example.com/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

$headers = array();
$headers[] = 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36';
$headers[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3';
$headers[] = 'Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
curl_close($ch);
echo $result;
?>

不幸的是,这样它仍然显示错误消息。

这意味着,对于我想要访问网站的 Web 服务器,必须有任何东西使命令行访问看起来与浏览器访问不同。但它是什么?

【问题讨论】:

    标签: php apache http server


    【解决方案1】:

    cURL 请求和浏览器发出的请求之间没有区别,除了它请求的 HTTP 标头之外,浏览器在客户端上运行 JavaScript。

    唯一标识 HTTP 客户端的是它的标头——通常是用户代理字符串——并且看到您已将用户代理设置为与浏览器完全相同,因此必须进行其他检查。

    默认情况下,cURL 不发送任何默认的Accept 标头,而浏览器请求带有此标头的页面以显示浏览器的功能。我希望网络服务器会检查这样的事情。

    看看上面的 Chrome 开发者工具截图。它允许您将整个请求复制为 cURL 请求,包括从 Chrome 发送的所有标头,以便在终端中进行测试。

    尝试完全匹配 PHP 中的所有标头,我确信 Web 服务器将无法将您识别为脚本。

    【讨论】:

    • 如果可以,请与我们分享实际的网站,我们将看看发生了什么。
    • 嘿格雷格,知道为什么它仍然不起作用。 (请看我上面编辑的问题。)
    • @David 当我运行您添加到已编辑答案中的确切代码并使用您之前评论中发布的 URL 进行更改时,该页面会按照我的预期进行回显。我看到了整个 HTML 结构。我的 PHP 版本是 PHP 7.2.24-0ubuntu0.19.04.1 (cli)。
    • @David no,Sicherheitsüberprüfung 不会出现在 Chrome、Firefox 或 cURL 中。
    【解决方案2】:

    您应该尝试通过伪造“真实”http 请求来模仿真实浏览器。添加比用户代理更多的标题,例如“Accept”、“Accept-Language”、“Accept-Encoding”。此外,您可能需要接受(并正确处理)cookie。 如果您的目标网站使用 javascript 来检测真正的浏览器,这是另一个挑战。

    【讨论】:

    • 我已经尝试了很多标题,但我会尝试更多。即使禁用了 JavaScript,我也可以使用浏览器访问该网站。所以,应该不是 JavaScript 的问题吧?
    • 我同意。也许一些基于cookies的检测。尝试在禁用 JS 的情况下启动一个私有浏览器窗口,看看它是否有效。
    • 我清除了缓存和cookies,启用了“阻止所有cookies”功能并打开了一个私人浏览器窗口,我仍然可以正常访问该网站。所以它不应该是一个 cookie 的东西,对吧?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-10
    • 2016-06-24
    • 1970-01-01
    相关资源
    最近更新 更多