curl_setopt 设置 user-agent 易被识破因 ua 过假、静态,需随机多端真实 ua 并同步 accept、accept-language、sec-ch-ua 等头;代理须高匿且轮换,延时需随机化(0.8–2 秒),cookie 应用 curlopt_cookiejar/file 自动管理,请求后校验响应内容而非仅状态码。

curl_setopt 设置 User-Agent 为什么总被识破?
很多 PHP 爬虫一上来就硬塞一个 Chrome UA,结果几页就 403 —— 不是因为没设,而是设得太假、太静态。网站会比对 UA 字符串的合理性(比如版本号是否过时)、与 Accept、Accept-Language 等头字段是否匹配,甚至结合 TLS 指纹判断真伪。
- 别只填一个 UA,用数组存
$user_agents,每次array_rand()随机取;至少包含 Chrome、Firefox、Safari 的 Win/macOS/iOS 多端组合 - 必须同步设置
Accept、Accept-Language、Sec-Ch-Ua(Chromium 浏览器需带这个),否则高防站点直接拒收 - 避免使用已知爬虫 UA 库里的“通用字符串”,比如
Mozilla/5.0 (X11; Linux x86_64)这类服务器 UA,一眼就被标记
代理 IP 轮换不是加个 CURLOPT_PROXY 就完事
随便扔一个免费代理进 curl_setopt($ch, CURLOPT_PROXY, $proxy),大概率超时或返回空响应——因为多数免费代理是透明型,目标站一查 X-Forwarded-For 或 TLS 指纹,立刻封掉整个代理池。
- 优先选高匿(Elite)代理,验证方式:请求
http://httpbin.org/ip,确认响应 body 中的 IP 和你传的代理 IP 一致,且响应头不含X-Forwarded-For - 别让同一个代理连续请求超过 3–5 次,用
array_shift()+array_push()实现简单轮转队列 - 配合
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 8)和CURLOPT_TIMEOUT防卡死,失败后自动切下一个代理
sleep() 和 usleep() 控制频率,但要注意单位陷阱
写 sleep(1) 看似每秒一次,实际可能因 DNS 解析、SSL 握手、网络抖动导致真实间隔远小于 1 秒,触发速率限制;而 usleep(500000)(半秒)在高并发下仍可能被识别为规律行为。
- 用
usleep(rand(800000, 2000000))替代固定延时,范围拉大到 0.8–2 秒,更贴近真人操作节奏 - 避免在循环开头统一延时,应放在
curl_exec()之后、下次请求之前,否则首次请求前也等,浪费时间 - 如果目标站有 Referer 校验(比如从列表页跳详情页),记得在延时后补上
Referer头,否则会被当异常流量拦截
Cookie 和登录态怎么“续”才不掉?
很多人模拟登录后把 Set-Cookie 字符串手动拼成 Cookie: a=1; b=2 发过去,结果第二页就 302 跳登录页——问题出在 Cookie 有效期、Domain、Path、Secure 属性没对齐,或者漏了 HttpOnly 字段对应的 session ID。
立即学习“PHP免费学习笔记(深入)”;
- 别手拼 Cookie,用
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt')自动保存,再用CURLOPT_COOKIEFILE复用,cURL 会处理所有属性 - 登录请求必须带上
Content-Type: application/x-www-form-urlencoded,且POST数据用http_build_query()编码,否则表单校验失败 - 若目标站用 JWT 或 localStorage 存 token,PHP curl 拿不到 JS 上下文,得换方案:用 headless Chrome(如 puppeteer-php)或退一步,抓包分析 token 生成逻辑
Content-Length,有些站不返回 403,而是静默返回空 HTML 或验证码页面,这时候光看 HTTP 状态码会误判成功。











