如何用PHP模拟自动更新Cookie的网页程序化访问?
首先,你遇到的问题本质是:浏览器会自动跟踪响应头里的Set-Cookie字段,把新的Cookie保存下来,下次请求同一个域名时自动带上最新的Cookie;但你一开始硬编码了Cookie,当服务器返回新的Cookie后,你的PHP代码没有更新这个值,所以后续请求就失效了。
要解决这个问题,你需要手动实现一个Cookie存储(Cookie Jar),每次请求后从响应头里提取Set-Cookie并更新存储,下次请求时再把最新的Cookie放到请求头里。下面是具体的实现思路和代码示例:
核心步骤
- 维护一个变量来存储当前有效的Cookie键值对
- 每次发送HTTP请求后,解析响应头中的
Set-Cookie字段,更新Cookie存储 - 下次请求时,把Cookie存储中的键值对格式化为
Cookie: key1=value1; key2=value2的形式放到请求头里
代码实现示例
先写一个简单的Cookie处理函数,再结合请求流程:
// 初始化Cookie存储,用来保存当前有效的Cookie $cookieJar = []; /** * 解析响应头中的Set-Cookie,更新CookieJar * @param array $headers 响应头数组 * @param array $cookieJar 要更新的Cookie存储 */ function updateCookieJar($headers, &$cookieJar) { foreach ($headers as $header) { // 查找Set-Cookie开头的头 if (stripos($header, 'Set-Cookie:') === 0) { $cookieStr = substr($header, 12); // 拆分Cookie的键值对和属性(只提取name=value部分,忽略expires、path等) $parts = explode(';', $cookieStr); $cookiePair = trim($parts[0]); list($key, $value) = explode('=', $cookiePair, 2); // 更新CookieJar,同名Cookie会被覆盖 $cookieJar[$key] = $value; } } } /** * 发送带Cookie的GET请求,并自动更新CookieJar * @param string $url 要请求的URL * @param array $cookieJar 当前的Cookie存储 * @return string 请求返回的内容 */ function getWithCookie($url, &$cookieJar) { // 格式化Cookie头 $cookieHeader = ''; if (!empty($cookieJar)) { $cookieParts = []; foreach ($cookieJar as $key => $value) { $cookieParts[] = "$key=$value"; } $cookieHeader = 'Cookie: ' . implode('; ', $cookieParts) . "\r\n"; } // 构建请求上下文 $opts = [ 'http' => [ 'method' => "GET", 'header' => "Accept-language: en\r\n" . $cookieHeader . "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36\r\n" ] ]; $context = stream_context_create($opts); // 发送请求 $content = file_get_contents($url, false, $context); // 获取响应头,更新CookieJar $responseHeaders = $http_response_header; // 这是PHP的全局变量,请求后会自动填充 updateCookieJar($responseHeaders, $cookieJar); return $content; } // 用法示例 $url = '你的目标网页URL'; // 第一次请求,会获取初始Cookie(如果服务器返回Set-Cookie) $content1 = getWithCookie($url, $cookieJar); // 第二次请求,自动带上更新后的Cookie $content2 = getWithCookie($url, $cookieJar);
补充说明
- 上面的代码只处理了最基础的Cookie场景,如果需要更严谨的处理(比如Cookie的domain、path、expires、secure、httponly等属性),你需要完善
updateCookieJar函数,判断当前请求的URL是否符合Cookie的适用范围,过期的Cookie要从Jar中移除。 - 如果你觉得自己实现Cookie处理太麻烦,可以考虑使用PHP的cURL扩展,它自带CookieJar功能,用
CURLOPT_COOKIEJAR和CURLOPT_COOKIEFILE参数就能自动处理Cookie的保存和携带,比手动处理更可靠:
$url = '你的目标网页URL'; $cookieFile = tempnam(sys_get_temp_dir(), 'cookie'); // 临时Cookie文件 // 初始化cURL $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36'); curl_setopt($ch, CURLOPT_ACCEPT_LANGUAGE, 'en'); curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile); // 保存响应的Cookie到文件 curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile); // 从文件读取Cookie到请求头 // 第一次请求 $content1 = curl_exec($ch); // 第二次请求,自动带上更新后的Cookie $content2 = curl_exec($ch); curl_close($ch); unlink($cookieFile); // 用完删除临时文件
用cURL的方式会更省心,因为它完全模拟了浏览器的Cookie处理逻辑,不需要自己去解析各种Cookie属性。
内容的提问来源于stack exchange,提问作者rikkitikkitumbo
相关产品推荐
相关产品推荐

