除了 CURLOPT_COOKIEFILE 之外,如何使用 PHP curl 发送 cookie?

Posted

技术标签:

【中文标题】除了 CURLOPT_COOKIEFILE 之外,如何使用 PHP curl 发送 cookie?【英文标题】:How can I send cookies using PHP curl in addition to CURLOPT_COOKIEFILE? 【发布时间】:2013-05-28 03:33:46 【问题描述】:

提交表单后,我正在从网站上抓取一些内容。问题是脚本时不时地失败,比如说 5 次中有 2 次脚本失败。我正在使用 php curl、COOKIEFILE 和 COOKIEJAR 来处理 cookie。但是,当我观察浏览器发送的标头(从浏览器访问目标网站并使用实时 http 标头时)和 php 发送的标头时,发现有很多差异。

我的浏览器发送的 cookie 变量比 php curl 多得多。我认为这种差异可能是因为 javascript 可用于设置大多数 cookie,但我不确定。

我正在使用下面的代码进行抓取,并显示我的浏览器和 php curl 的已发送标头:

$ckfile = tempnam ("/tmp", 'cookiename');

$url = 'https://www.domain.com/firststep';
$poststring = 'variable1=4&variable2=5';
$ch = curl_init ($url);
curl_setopt ($ch, CURLOPT_COOKIEJAR, $ckfile);
curl_setopt ($ch, CURLOPT_COOKIEFILE, $ckfile);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $poststring);
$output = curl_exec ($ch);
curl_close($ch);



$url = 'https://www.domain.com/nextstep';
$poststring = 'variableB1=4&variableB2=5';
$ch = curl_init ($url);
curl_setopt ($ch, CURLOPT_COOKIEJAR, $ckfile);
curl_setopt ($ch, CURLOPT_COOKIEFILE, $ckfile);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $poststring);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
$output = curl_exec ($ch);
$headers = curl_getinfo($ch, CURLINFO_HEADER_OUT);
curl_close($ch);

print_r($headers);

// Gives:
POST /d-cobs-web/doffers.html;jsessionid=7BC2A5277A4EB07D9A7237A707BE1366 HTTP/1.1
User-Agent: Mozilla
Host: domain.subdomain.nl
Accept: */*
Cookie: JSESSIONID=7BC2A5277A4EB07D9A7237A707BE1366; www-20480=MIFBNLFDFAAA
Content-Length: 187
Content-Type: application/x-www-form-urlencoded

// Where live http headers gives:
POST /d-cobs-web/doffers.html;jsessionid=7BC2A5277A4EB07D9A7237A707BE1366 HTTP/1.1
Host: domain.subdomain.nl
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: nl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: https://domain.subdomain.nl/dd/doffers.html?returnUrl=https%3A%2F%2Fttcc.subdomain.nl%2Fdd%2Fpreferences.html%3FValueChanged%3Dfalse&BEGBA=&departureDate=13-06-2013&extChangeTime=&pax2=0&bp=&pax1=1&pax4=0&bk=&pax3=0&shopId=&xtpage=&partner=NSINT&bc=&xt_pc=&ov=&departureTime=&comfortClass=2&destination=DEBHF&thalysTicketless=&beneUser=&debugDOffer=&logonId=&valueChanged=&iDomesticOrigin=&rp=&returnTime=&locale=nl_NL&vu=&thePassWeekend=false&returnDate=&xtsite=&pax=A&lc2=&lc1=&lc4=&lc3=&lc6=&lc5=&BECRA=&passType2=&custId=&lc9=&iDomesticDestination=&passType1=A&lc7=&lc8=&origin=NLASC&toporef=&pid=&passType4=&returnTimeType=1&passType3=&departureTimeType=1&socusId=&idr3=&xtn2=&loyaltyCard=&idr2=&idr1=&thePassBusiness=false&cid=14812
Content-Length: 219
Cookie: subdomainPARTNER=NSINT; JSESSIONID=CB3FEB3AC72AD61A80BFED91D3FD96CA; www-20480=MHFBNLFDFAAA; campaignPos=5; www-47873=MGFBNLFDFAAA; __utma=1.993399624.1370027094.1370040145.1370082133.5; __utmc=1; __utmz=1.1370027094.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); BCSessionID=5dc05787-c2c8-43e1-9abe-93989970b087; BCPermissionLevel=PERSONAL; __utmb=1.1.10.1370082133
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
AJAXREQUEST=_viewRoot&doffersForm=doffersForm&doffersForm%3AvalueChanged=&doffersForm%3ArequestValid=true&javax.faces.ViewState=j_id3&doffersForm%3Aj_id937=doffersForm%3Aj_id937&valueChanged=false&AJAX%3AEVENTS_COUNT=1&

我想使用:

$headers   = array();
$headers[] = 'Cookie: ' . $cookie;

和:

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

地点:

$cookie = 'subdomainPARTNER=NSINT; JSESSIONID=CB3FEB3AC72AD61A80BFED91D3FD96CA; www-20480=MHFBNLFDFAAA; campaignPos=5; www-47873=MGFBNLFDFAAA; __utma=1.993399624.1370027094.1370040145.1370082133.5; __utmc=1; __utmz=1.1370027094.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); BCSessionID=5dc05787-c2c8-43e1-9abe-93989970b087; BCPermissionLevel=PERSONAL; __utmb=1.1.10.1370082133';

上面cookie中的一些参数我可能可以从网站的内容中抓取,但不是全部。其中一些我可能可以从 $ckfile 中读取,但我不知道该怎么做。特别是 utma utmc、utmz、utmcsr、utmccn、utmcmd 我无法从任何地方获得,我认为这些是由 javascript 生成的。

问题 1: 我在当前代码中的 cookie 处理是否有问题,因为 php curl 发送的 cookie 变量很少,而浏览器发送的更多?进一步:浏览器和 php curl 发送的标头之间的其他差异是否会成为返回正确内容的问题?

问题 2: 缺少 cookie 变量是因为 javascript 设置了这些 cookie 吗?

问题 3: 处理 cookie 以确保将所有必需的 cookie 发送到远程服务器的最佳方法是什么?

非常欢迎您的帮助!

【问题讨论】:

你有没有得到这个?我遇到了同样的问题 - 想知道为什么浏览器发送 3 个 cookie 而 curl 只发送 1 个,尽管 cookie 文件包含所有 3 个。 嗯...听起来像是我正在抓取 backpage.com 的问题。 【参考方案1】:

如果 cookie 是从脚本生成的,那么您可以手动发送 cookie 以及文件中的 cookie(使用 cookie-file 选项)。例如:

# sending manually set cookie
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Cookie: test=cookie"));

# sending cookies from file
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile);

在这种情况下,curl 将发送您定义的 cookie 以及文件中的 cookie。

如果cookie是通过javascrript生成的,那么你必须跟踪它是如何生成的,然后你可以使用上面的方法(通过http-header)发送它。

当从 Mozilla 发送 cookie 时会看到 utma utmc, utmz。你不应该再担心这些事情了。

最后,你的做法没问题。只需确保您使用文件名的绝对路径(即/var/dir/cookie.txt)而不是相对路径。

使用 curl 时始终启用详细模式。它将在跟踪请求方面帮助您很多。它还可以为您节省很多时间。

curl_setopt($ch, CURLOPT_VERBOSE, true);

【讨论】:

保存的cookie文件是否包含test=cookie?如果没有,那么我将如何获取 cURL 以从自定义标头请求中保存 cookie? @brant cookie 文件仅基于来自服务器的Set-cookie 响应标头写入。如果服务器没有返回带有该标头的 cookie,这种情况将被忽略。 curl_setopt 调用的顺序非常重要。设置 CURLOPT_POST after CURLOPT_POSTFIELDS 并且您迷失在难以找到的错误中......同样,上述解决方案中的顺序对于保持。交换它,您只需使用“test=cookie”覆盖 cookie 文件中的所有内容 对我来说,它不起作用。你必须传递一对 key&value 才能工作 curl_setopt($ch, CURLOPT_HTTPHEADER, array("Cookie" => "test=cookie"));【参考方案2】:

这里是发送 cookie 的示例列表 - https://github.com/andriichuk/php-curl-cookbook#cookies

$curlHandler = curl_init();

curl_setopt_array($curlHandler, [
CURLOPT_URL => 'https://httpbin.org/cookies',
CURLOPT_RETURNTRANSFER => true,

CURLOPT_COOKIEFILE  => $cookieFile,
CURLOPT_COOKIE => 'foo=bar;baz=foo',

/**
 * Or set header
 * CURLOPT_HTTPHEADER => [
       'Cookie: foo=bar;baz=foo',
   ]
 */
]);

$response = curl_exec($curlHandler);
curl_close($curlHandler);

echo $response;

【讨论】:

【参考方案3】:

试试下面的代码,

$cookieFile = "cookies.txt";
if(!file_exists($cookieFile)) 
    $fh = fopen($cookieFile, "w");
    fwrite($fh, "");
    fclose($fh);



$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiCall);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonDataEncoded);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile); // Cookie aware
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile); // Cookie aware
curl_setopt($ch, CURLOPT_VERBOSE, true);
if(!curl_exec($ch))
    die('Error: "' . curl_error($ch) . '" - Code: ' . curl_errno($ch));

else
    $response = curl_exec($ch); 

curl_close($ch);
$result = json_decode($response, true);

echo '<pre>';
var_dump($result);
echo'</pre>';

我希望这会对你有所帮助。

最好的问候, 达西塔。

【讨论】:

【参考方案4】:

我认为您需要的唯一 cookie 是 JSESSIONID=xxx..

也永远不要共享您的 cookie,因为有人可能会以这种方式访问​​您的个人数据。特别是当 cookie 是会话时。一旦您退出网站,这些 cookie 将停止工作。

【讨论】:

以上是关于除了 CURLOPT_COOKIEFILE 之外,如何使用 PHP curl 发送 cookie?的主要内容,如果未能解决你的问题,请参考以下文章

除了加载行子集之外,使用 NSFetchedResultsController 有啥好处

sklearn 除了文本之外的其他输入用于文本分类

除了给定字符串之外,匹配任何内容的 JavaScript 模式是啥? [复制]

除了编码之外,如何自动执行 TFS 检查?

为啥除了 _view 之外都设置了 IBOutlets?

一组外键,其中除了一个之外都是 NULL