有网站,当我在浏览器上打开特定的ajax请求时我得到了结果页面,但是当我尝试用curl加载它们时,我从服务器收到错误.
如何正确模拟对模拟浏览器的服务器的get请求?
这就是我正在做的事情:
$url="https://new.aol.com/productsweb/subflows/ScreenNameFlow/AjaxSNAction.do?s=username&f=firstname&l=lastname";
ini_set('user_agent', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT
5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
$result=curl_exec($ch);
print $result;
Run Code Online (Sandbox Code Playgroud)
Vol*_*erK 66
你确定curl模块符合ini_set('user_agent',...)吗?在http://docs.php.net/function.curl-setopt中有一个选项CURLOPT_USERAGENT .
是否还有服务器测试过的cookie?您可以使用CURLOPT_COOKIE,CURLOPT_COOKIEFILE和/或CURLOPT_COOKIEJAR来处理.
编辑:由于请求使用https,验证证书时可能也会出错,请参阅CURLOPT_SSL_VERIFYPEER.
$url="https://new.aol.com/productsweb/subflows/ScreenNameFlow/AjaxSNAction.do?s=username&f=firstname&l=lastname";
$agent= 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)';
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $agent);
curl_setopt($ch, CURLOPT_URL,$url);
$result=curl_exec($ch);
var_dump($result);
Run Code Online (Sandbox Code Playgroud)
han*_*rik 10
我举个例子,首先决定你想模拟什么浏览器,在这种情况下我选择了Firefox 60.6.1esr (64-bit),并检查它发出什么 GET 请求,这可以通过一个简单的 netcat 服务器获得(MacOS 捆绑 netcat,大多数 linux 发行版捆绑 netcat, Windows 用户可以从.. Cygwin.org 等地方获取 netcat),
设置 netcat 服务器以侦听端口 9999: nc -l 9999
现在在 Firefox 中点击http://127.0.0.1:9999,我得到:
$ nc -l 9999
GET / HTTP/1.1
Host: 127.0.0.1:9999
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Run Code Online (Sandbox Code Playgroud)
现在让我们将其与这个简单的脚本进行比较:
<?php
$ch=curl_init("http://127.0.0.1:9999");
curl_exec($ch);
Run Code Online (Sandbox Code Playgroud)
我得到:
$ nc -l 9999
GET / HTTP/1.1
Host: 127.0.0.1:9999
Accept: */*
Run Code Online (Sandbox Code Playgroud)
这里有几个缺少的标头,它们都可以用 curl_setopt 的 CURLOPT_HTTPHEADER 选项添加,但User-Agent具体应该用 CURLOPT_USERAGENT 设置(它会在多次调用 curl_exec() 时保持不变,如果你使用 CURLOPT_FOLLOWLOCATION 那么它会保持不变http 重定向),并且Accept-Encoding标头应该用 CURLOPT_ENCODING 设置(如果它们用 CURLOPT_ENCODING 设置,那么如果服务器选择压缩响应,curl 将自动解压缩响应,但如果您通过 CURLOPT_HTTPHEADER 设置它,那么您必须手动检测并自己解压缩内容,这很麻烦而且完全没有必要,一般来说)所以添加我们得到的内容:
<?php
$ch=curl_init("http://127.0.0.1:9999");
curl_setopt_array($ch,array(
CURLOPT_USERAGENT=>'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0',
CURLOPT_ENCODING=>'gzip, deflate',
CURLOPT_HTTPHEADER=>array(
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: en-US,en;q=0.5',
'Connection: keep-alive',
'Upgrade-Insecure-Requests: 1',
),
));
curl_exec($ch);
Run Code Online (Sandbox Code Playgroud)
现在运行该代码,我们的 netcat 服务器得到:
$ nc -l 9999
GET / HTTP/1.1
Host: 127.0.0.1:9999
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept-Encoding: gzip, deflate
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Run Code Online (Sandbox Code Playgroud)
瞧!我们的 php 模拟 browserGET 请求现在应该与真实的 firefox GET 请求没有区别:)
下一部分只是吹毛求疵,但如果仔细观察,您会发现标头以错误的顺序堆叠,firefox 将Accept-Encoding标头放在第 6 行,而我们模拟的 GET 请求将其放在第 3 行......以修复这样,我们可以手动将 Accept-Encoding 标头放在正确的行中,
<?php
$ch=curl_init("http://127.0.0.1:9999");
curl_setopt_array($ch,array(
CURLOPT_USERAGENT=>'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0',
CURLOPT_ENCODING=>'gzip, deflate',
CURLOPT_HTTPHEADER=>array(
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: en-US,en;q=0.5',
'Accept-Encoding: gzip, deflate',
'Connection: keep-alive',
'Upgrade-Insecure-Requests: 1',
),
));
curl_exec($ch);
Run Code Online (Sandbox Code Playgroud)
运行它,我们的 netcat 服务器得到:
$ nc -l 9999
GET / HTTP/1.1
Host: 127.0.0.1:9999
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Run Code Online (Sandbox Code Playgroud)
问题解决了,现在标题的顺序是正确的,并且请求似乎与真实的 firefox 请求完全无法区分:)(我实际上并不推荐这最后一步,保持 CURLOPT_ENCODING 与自定义 Accept-Encoding 标头,我从未遇到过标头顺序很重要的情况)