返回博客
网络爬虫技术
Raluca PenciucLast updated on Mar 31, 20262 min read

HTTP 头部入门:如何利用它们进行高效的网页抓取

HTTP 头部入门:如何利用它们进行高效的网页抓取

网络爬虫是从中提取有价值信息的绝佳工具,但说实话,当你的爬虫脚本被封锁时,确实会让人感到相当沮丧。

这就像一场猫捉老鼠的游戏,网站所有者总在想方设法把你挡在门外。不过,你的工具箱里有一件秘密武器,能让你占据上风:HTTP 头部和 Cookie。

这两个要素在你的爬虫脚本与网站的交互过程中起着至关重要的作用,掌握它们可能意味着爬取任务是被封锁还是成功。

在本教程中,我们将揭开 HTTP 头部和 Cookie 的奥秘,并向您展示如何利用它们让您的爬取行为尽可能地像人类一样。

您将了解网络爬虫中最常用的头部信息,学习如何从真实浏览器中获取头部信息和Cookie,以及如何利用自定义头部信息绕过安全防护措施。那么,让我们深入探讨,看看如何将爬虫技术提升到一个新的高度!

理解 HTTP 头部

HTTP 头部是作为 HTTP 请求或响应的一部分发送的键值对。它们由冒号和空格分隔,且名称(键)不区分大小写。

您可以根据 HTTP 头部的功能及其发送方向,将其归类为不同类别。这些类别包括:

  • 通用标头:同时适用于请求和响应消息
  • 请求头:包含关于您要获取的资源或发起请求的客户端的更多信息
  • 响应头:包含关于响应的附加信息,例如其位置或提供响应的服务器
  • 实体标头:包含资源正文的相关信息,例如其大小或 MIME 类型
  • 扩展标头:用于提供向后兼容性

HTTP 标头提供了广泛的信息,包括您正在发起的请求类型、您使用的浏览器,以及服务器处理请求所需的任何其他信息。

它们还允许您提供身份验证和安全信息、控制缓存和压缩,并指定请求的语言和字符集。

例如,以下是 Chrome 访问 youtube.com 时发送的头部信息:

:authority: www.youtube.com

:method: GET

:path: /

:scheme: https

accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9

accept-encoding: gzip, deflate, br

accept-language: en-US,en;q=0.9

cache-control: no-cache

pragma: no-cache

referer: https://www.google.com/

sec-ch-ua: "Not_A Brand";v="99", "Google Chrome";v="109", "Chromium";v="109"

sec-ch-ua-arch: "x86"

sec-ch-ua-bitness: "64"

sec-ch-ua-full-version: "109.0.5414.75"

sec-ch-ua-full-version-list: "Not_A Brand";v="99.0.0.0", "Google Chrome";v="109.0.5414.75", "Chromium";v="109.0.5414.75"

sec-ch-ua-mobile: ?0

sec-ch-ua-model: ""

sec-ch-ua-platform: "Windows"

sec-ch-ua-platform-version: "15.0.0"

sec-ch-ua-wow64: ?0

sec-fetch-dest: document

sec-fetch-mode: navigate

sec-fetch-site: same-origin

sec-fetch-user: ?1

upgrade-insecure-requests: 1

user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36

x-client-data: CIm2yQEIorbJAQjEtskBCKmdygEI5PDKAQiWocsBCKr2zAEI7oLNAQibiM0BCLqIzQEI9YjNAQ==

Decoded:

message ClientVariations {

  // Active client experiment variation IDs.

  repeated int32 variation_id = [3300105, 3300130, 3300164, 3313321, 3324004, 3330198, 3357482, 3359086, 3359771, 3359802, 3359861];

}

Web Cookie(或称 HTTP Cookie)是网站存储在用户浏览器中的小型文本文件。此后,每当用户向该网站发送新请求时,Cookie 都会自动包含在内。

Cookie具有唯一标识性,可分为以下类型:

  • 会话 Cookie:属于临时性,在用户关闭浏览器时失效
  • 持久性 Cookie:具有特定的过期日期,会在用户设备上保留至过期或被用户删除为止。

网站利用 Cookie 来个性化用户的体验。这可能包括记住用户的登录信息、保存购物车内容,以了解用户如何与网站互动,并提供定向广告。

同样以 youtube.com 为例,我们可以观察到这些 Cookie 存储了哪些信息:

cookie: CONSENT=YES+srp.gws-20210816-0-RC3.ro+FX+801; __Secure-3PAPISID=jG4abs_wYhyzcDG5/A2yfWlePlb1U9fglf; VISITOR_INFO1_LIVE=pJuwGIYiJlE; __Secure-3PSIDCC=AEf-XMRV_MjLL0AWdGWngxFHvNUF3OIpk3_jdeUwRiZ76WZ3XsSY0Vlsl1jM9n7FLprKTqFzvw; __Secure-3PSID=RAi8PYLbf3qLvF1oEav9BnHK_eOXwimNM-0xwTQPj1-QVG1Xwpz17T4d-EGzT6sVps1PjQ.; YSC=4M3JgZEwyiA; GPS=1; DEVICE_INFO=ChxOekU1TURJMk1URTBOemd5TWpJeU5qVTJOdz09EOvgo54GGOvgo54G; PREF=tz=Europe.Bucharest&f6=40000000&f4=4000000; CONSISTENCY=ACHmjUr7DnoYSMf5OL-vaunKYfoLGz1lWYRUZRepFyIBDRpp_jrEa85E4wgRJLJ2j15l688hk9IVQu7fIjYXo7sdsZamArxVHTMuChgHd22PkX_mbfifnMjyp4OX2swyQJRS-8PE6cOCt_6129fGyBs; amp_adc4c4=Ncu7lbhgeiAAYqecSmyAsS.MXVDWTJjd3BXdmRkQ3J0YUpuTkx3OE5JcXVKMw==..1gn4emd4v.1gn4en556.0.4.4

在网页抓取中,您可以利用头部信息和Cookie绕过安全措施并访问受限内容,同时提供有助于将您的抓取脚本识别为合法浏览器的信息。

例如,通过指定正确的 User-Agent 头部(更多细节见下一节),您可以让脚本伪装成 Chrome 浏览器,从而避免被网站检测到。

此外,通过存储和发送 Cookie,您的爬虫可以访问仅对已登录用户开放的内容。由于网站使用 Cookie 来提供定向广告,您也可以利用它们来提取更准确的数据,从而更好地了解该网站。

除了调整 HTTP 头部和 Cookie 之外,还请参考本指南中列出的若干非常实用的网络爬虫最佳实践。

网络爬虫中常用的头部信息

网络爬虫可使用的头部信息种类繁多,但最常用的包括:

User-Agent

该标头用于识别发起请求的客户端所使用的浏览器和操作系统。服务器会利用这些信息判断客户端的浏览器及操作系统,从而提供相应的内容和功能。

User-Agent 字符串包含浏览器名称、版本和平台等信息。例如,Windows 系统上 Google Chrome 的 User-Agent 字符串可能如下所示:

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36

在网页抓取中,通过指定属于常见网页浏览器的 User-Agent,您可以让脚本伪装成合法用户常用的浏览器,从而降低被封锁的风险。

Accept

该标头用于指定浏览器在响应 HTTP 请求时愿意接受的内容类型,例如文本、图像、音频或视频。一个 Accept 标头可能如下所示:

Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8

在网页抓取中,通过指定正确的 Accept 头,可以确保脚本接收正确的数据。例如,若要抓取 HTML 页面,可将 Accept 头指定为 text/html

然而,部分网站可能利用此标头检测爬虫,因此务必谨慎使用,仅在必要时才启用。

Accept-Language

该标头指定了浏览器在响应 HTTP 请求时愿意接受的内容首选语言。服务器会利用 Accept-Language 标头来确定应向客户端发送哪种语言的内容。

请求英文HTML页面的浏览器可能会发送如下格式的Accept-Language标头:

Accept-Language: en-US,en;q=0.9

网站会在收到请求后使用此标头向客户端发送 Cookie。Cookie 标头可能如下所示:

Cookie: session_id=1234567890; user_id=johndoe

在网页抓取中,您可以利用此标头传递会话 Cookie,从而访问仅限登录用户查看的内容。另一种应用场景是使用持久性 Cookie 获取个性化结果。

Referer

该标头指定了用户通过链接跳转至当前页面时,所来自的前一个网页的 URL。服务器利用它来追踪请求的来源并理解请求的上下文。

例如,当用户点击网页上的链接跳转至另一个网页时,浏览器会在向第二个网页发送请求时,在 Referer 头部包含第一个网页的 URL。因此,对第二个网页的请求中,Referer 头部将呈现如下形式:

Referer: https://www.example.com/

在网页抓取中,您可以利用 Referer 标头访问那些不允许直接请求的网站。

理论部分就到此为止。接下来让我们看看如何提取发送到网站的 HTTP 头部和 Web Cookie。

回到我们的示例,在真实浏览器中访问 youtube.com。然后在页面任意位置右键点击,选择“检查”选项。开发者工具打开后,切换到“网络”标签页。

刷新页面后,您将看到请求实时加载。点击第一个(也是主要的)请求,会弹出一个新标签页。

在这里,你可以查看所发送请求的所有详细信息:URL、方法、状态码、远程地址,以及最重要的:我们正在寻找的请求和响应头部。

在网页抓取中使用自定义头部

  • 使用 httpbin.org 展示浏览器发送的头部信息
  • 选择一种编程语言并发送一个基本的 GET 请求以查看头部信息
  • 传入您获取的自定义头部
  • 对 Node.js 和 Python 重复此过程
  • 重写 WSA 相关章节 - 添加 API 文档链接 - 描述自定义头部的功能

现在让我们看看如何利用这些头部信息来改进我们的爬虫。在此部分,我们将以一个简单的镜像网站为例,该网站会直接显示我们发送的头部信息:https://httpbin.org/headers

复制“headers”对象的内容,开始编写代码。

Node.js

确认 Node.js 环境已正确配置且项目已初始化后,运行以下代码:

import got from 'got';

(async () => {

    const response = await got('https://httpbin.org/headers')

    console.log(response.body)

})()

这样我们就能看到最基本的 GET 请求是什么样子的。结果应为:

{

  "headers": {

    "Accept-Encoding": "gzip, deflate, br",

    "Host": "httpbin.org",

    "User-Agent": "got (https://github.com/sindresorhus/got)",

    "X-Amzn-Trace-Id": "Root=1-63c93ff5-0c352d6319620b3d6b46df02"

  }

}

这与我们在浏览器中看到的情况大不相同。仅凭 User-Agent 这一项,服务器就很容易检测出该请求是自动生成的。

现在让我们传递自定义头部信息并再次发送请求:

import got from 'got';

(async () => {

    const custom_headers = {

        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",

    	  "Accept-Encoding": "gzip, deflate, br",

    	  "Accept-Language": "en-US,en;q=0.9",

    	  "Cache-Control": "no-cache",

    	  "Cookie": "amp_d915a9=sd12OA1w0P4xMKsMYSmY9n.MXVDWTJjd3BXdmRkQ3J0YUpuTkx3OE5JcXVKMw==..1ggrl757h.1ggrl75ci.0.1o.1o; amp_adc4c4=P3ZIfUgU8qzSHI-y0gZvbk.MXVDWTJjd3BXdmRkQ3J0YUpuTkx3OE5JcXVKMw==..1gn51hk3v.1gn51lql7.0.e.e",

    	  "Host": "httpbin.org",

    	  "Pragma": "no-cache",

    	  "Sec-Ch-Ua": "\"Not_A Brand\";v=\"99\", \"Google Chrome\";v=\"109\", \"Chromium\";v=\"109\"",

    	  "Sec-Ch-Ua-Mobile": "?0",

    	  "Sec-Ch-Ua-Platform": "\"Windows\"",

    	  "Sec-Fetch-Dest": "document",

    	  "Sec-Fetch-Mode": "navigate",

    	  "Sec-Fetch-Site": "none",

    	  "Sec-Fetch-User": "?1",

    	  "Upgrade-Insecure-Requests": "1",

    	  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",

    	  "X-Amzn-Trace-Id": "Root=1-63c93e34-1ad0141279d49bfc28fb058e"

    }

    const response = await got('https://httpbin.org/headers', {

        headers: custom_headers

    })

    console.log(response.body)

})()

再次运行脚本后,你会发现,尽管我们并未实际打开 Chrome 浏览器,但请求看起来就像是从真实的 Chrome 浏览器发出的。

Python

现在让我们用 Python 尝试一下同样的操作。尽管语法和库不同,但原理完全相同。

import requests

url = 'https://httpbin.org/headers'

headers = {

	"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",

	"Accept-Encoding": "gzip, deflate, br",

	"Accept-Language": "en-US,en;q=0.9",

	"Cache-Control": "no-cache",

	"Cookie": "amp_d915a9=sd12OA1w0P4xMKsMYSmY9n.MXVDWTJjd3BXdmRkQ3J0YUpuTkx3OE5JcXVKMw==..1ggrl757h.1ggrl75ci.0.1o.1o; amp_adc4c4=P3ZIfUgU8qzSHI-y0gZvbk.MXVDWTJjd3BXdmRkQ3J0YUpuTkx3OE5JcXVKMw==..1gn51hk3v.1gn51lql7.0.e.e",

	"Host": "httpbin.org",

	"Pragma": "no-cache",

	"Sec-Ch-Ua": "\"Not_A Brand\";v=\"99\", \"Google Chrome\";v=\"109\", \"Chromium\";v=\"109\"",

	"Sec-Ch-Ua-Mobile": "?0",

	"Sec-Ch-Ua-Platform": "\"Windows\"",

	"Sec-Fetch-Dest": "document",

	"Sec-Fetch-Mode": "navigate",

	"Sec-Fetch-Site": "none",

	"Sec-Fetch-User": "?1",

	"Upgrade-Insecure-Requests": "1",

	"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",

	"X-Amzn-Trace-Id": "Root=1-63c93e34-1ad0141279d49bfc28fb058e"

}

response = requests.get(url, headers=headers)

print(response.text)

无论使用哪种编程语言,运行脚本后的结果都将完全一致。

WebScrapingAPI 中的自定义头部

任何值得信赖的爬取 API 都应提供向请求传递自定义 HTTP 头部Cookie 的强大功能。具体标准可能因 API 而异,因此请务必先查阅官方文档。

默认情况下,WebScrapingAPI 会在每次请求中提供一组自定义头部。随机 User-Agent 头部仅是其中一个示例。

然而,鉴于网站可能变得极其复杂或单纯过时,您可以自由禁用此行为并完全自定义请求。只需先获取 API 密钥,然后运行以下代码:

import got from 'got';

(async () => {

    const response = await got("https://api.webscrapingapi.com/v1", {

        searchParams: {

            api_key: "YOUR_API_KEY",

            url: "https://httpbin.org/headers",

            keep_headers: '0',

        },

        headers: {

            "Wsa-Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",

            "Wsa-Accept-Encoding": "gzip, deflate, br",

            "Wsa-Accept-Language": "en-US,en;q=0.9",

            "Wsa-Cache-Control": "no-cache",

            "Wsa-Cookie": "amp_d915a9=sd12OA1w0P4xMKsMYSmY9n.MXVDWTJjd3BXdmRkQ3J0YUpuTkx3OE5JcXVKMw==..1ggrl757h.1ggrl75ci.0.1o.1o; amp_adc4c4=P3ZIfUgU8qzSHI-y0gZvbk.MXVDWTJjd3BXdmRkQ3J0YUpuTkx3OE5JcXVKMw==..1gn51hk3v.1gn51lql7.0.e.e",

            "Wsa-Pragma": "no-cache",

            "Wsa-Sec-Ch-Ua": "\"Not_A Brand\";v=\"99\", \"Google Chrome\";v=\"109\", \"Chromium\";v=\"109\"",

            "Wsa-Sec-Ch-Ua-Mobile": "?0",

            "Wsa-Sec-Ch-Ua-Platform": "\"Windows\"",

            "Wsa-Sec-Fetch-Dest": "document",

            "Wsa-Sec-Fetch-Mode": "navigate",

            "Wsa-Sec-Fetch-Site": "none",

            "Wsa-Sec-Fetch-User": "?1",

            "Wsa-Upgrade-Insecure-Requests": "1",

            "Wsa-User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",

            "Wsa-X-Amzn-Trace-Id": "Root=1-63c93e34-1ad0141279d49bfc28fb058e"

        }

    })

    console.log(response.body)

})()

在此情况下,根据 API 文档,我们必须在请求头名称前添加“Wsa-”前缀才能将其传递至请求。此措施旨在防止意外请求头的传递,例如当 API 请求由浏览器发送时。

结论

本文概述了 HTTP 头部和 Web Cookie 在网页抓取中的重要性和用途。

我们探讨了标头和 Cookie 的定义,说明了如何利用它们访问受限内容并使您的抓取脚本伪装成合法浏览器,同时也介绍了它们在跟踪和分析中的应用。

此外,我们列举了网络爬虫中常用的部分头部,并讲解了如何从真实浏览器中获取头部和Cookie。随后,我们通过代码示例演示了如何在爬虫脚本中运用这些技术。

通过理解并有效运用头部信息和Cookie,您可以提升网络爬取工作的效率。掌握这些知识后,您将能将爬取技能提升到更高水平,从而从网络中提取有价值的信息。

关于作者
Raluca Penciuc, 全栈开发工程师 @ WebScrapingAPI
Raluca Penciuc全栈开发工程师

Raluca Penciuc 是 WebScrapingAPI 的全栈开发工程师,主要负责开发爬虫、优化规避机制,并探索可靠的方法以降低在目标网站上的被检测概率。

开始构建

准备好扩展您的数据收集规模了吗?

加入2,000多家企业,使用WebScrapingAPI在无需任何基础设施开销的情况下,以企业级规模提取网络数据。