基于R语言的自动数据收集:网络抓取和文本挖掘实用指南【2.2】
5.1.6 标头字段标头定义了接收到请求或响应后需要采取的行动。标头的内容可以是通用的也可以属于某个专用的组用于请求的标头字段、用于响应的标头字段以及关于正文的标头字段。例如请求标头字段可以把客户端能作为响应接受的资源类型告诉服务器比如限定响应的内容为纯HTML网页或给出客户端的技术参数比如用于请求网页的软件是哪个。它们也可以用来描述消息的内容如纯文本、二进制、图片或音频文件等也可以用到编码步骤如压缩。标头字段总是遵循相同的简单语法。它的名字在前并用冒号和后面的值分开。某些标头字段会包含用逗号分开的多个值。让我们通过一组普通而重要的标头字段示例来看它们的作用和用法。下面各个段落的概述会把标头名字设为粗体并把字段类型放在括号里以此说明该标头字段是用于请求、响应还是正文。Accept请求Accept是一个请求标头字段它告诉服务器哪种类型的资源是客户端愿意当作响应来接受的。如果服务器没有符合Accept约束条件的资源它就应该返回一个406状态码。可接受内容的规格遵循MIME类型模式。多个类型用逗号分开分号用于声明所谓的接受参数accept parameterstype/subtypeacceptparametervaluetype/http://www.hzcourse.com/resource/readBook? path/openresources/teach_ebook/uncompressed/15597/OEBPS/Text/...。星号*可以用来声明主类型type和从类型subtype的范围。content-type设置的规则如下1更明确的类型优先于更不明确的类型2多个类型的优先级根据q参数值从大到小递减3所有没有声明q参数的类型其默认设置为q1。上面的例子可以理解为客户端接受HTML和GIF如果这两者都没有其他类型的图片也可以。如果没有其他类型的图片客户端也能接受任何其他的内容类型。Accept-Encoding请求Accept-Encoding编码告诉服务器哪种编码或压缩方法是客户端可以接受的。如果服务器不能以指定编码发送内容它就应该返回一个406状态码。上面的例子可以理解为客户端接受gzip和deflate编码方式。如果两者都不能得到它也可以接受sdch否则无编码的内容也是可以的。但是它不接受任何其他的编码方式因为最后的接受参数值为0也就等于是不接受。Allow响应正文Allow告诉客户端哪些HTTP方法对于特定资源是允许的它会是状态码为405的响应的一部分。Authorization请求Authorization是向服务器传递用户名和密码的一种简单方式。用户名和密码首先合并为usernamepassword格式并根据Base64模式进行编码。编码的结果会出现在标头字段如上例所示。注意这个编码过程并没有进行加密而仅仅是确保所有的字符都包含在ASCII字符集中。我们会在5.2.2节更详细地讨论HTTP验证机制。上例中的Authorization标头字段声明了验证方法是Basic基本验证而以Base64模式编码的用户名-密码组合是cm9va2llOjEyM0lzTm90QVNlY3VyZVBX。Content-Encoding响应正文Content-Encoding声明的是被应用于响应内容的转换方式如压缩方法详见Accept-Encoding部分。Content-Length响应正文Content-Length给消息的接收方提供了有关内容大小的信息以OCTET8位字节存放的十进制数表示。Content-Type响应正文Content-Type提供了有关正文内容类型的信息。内容类型是用MIME类型描述的详见Accept部分。Cookie请求Cookie是从服务器发送的放在Set-Cookie标头字段里的信息。它们可以用于识别客户端——如果没有cookie服务器就无从知道它之前是否和某个客户端有过联系。Cookie标头字段则是在请求中把之前接收到的信息返给服务器。该标头字段的语法很简单Cookie字段是由namevalue的配对组成的每对之间用分号隔开。expires、domain、path和secure这些名字是保留参数定义了客户端处理cookie的方式。expires定义了cookie失效的日期。如果没有给定失效日期则cookie只能在一次会话中有效。domain和path说明了需要该cookie的是哪些资源请求。secure则用于指定cookie只能通过安全连接SSL见5.3.1节进行发送。我们会在5.2.1节更详细地介绍cookie。上面的例子可以理解为cookie sessionid2783321对于域www.r-datacollection.com及其所有子目录通过path/声明有效有效期截止到2035年12月31日。From请求From给网络爬虫或抓取程序的程序员提供了发送他们邮件地址的选项。这有助于网络管理员在发现违反授权的行为时联系那些控制自动抓取机器人和网络爬虫的人。这个标头字段对于网络抓取很有用我们会在5.2.1节讨论它。Host请求Host是HTTP/1.1版的请求里要求的标头字段在多个主机名重定向到同一个IP地址的情况下它会帮助服务器决定用哪一个URL。If-Modified-Since请求If-Modified-Since可以用于根据请求资源相关的时间戳来处理请求。如果服务器发现在这个标头字段提供的日期之后所请求的资源没有修改过它就应该返回一个304状态码没有修改。我们可以利用这个标头来编写更加高效和友好的网络抓取程序参见9.3.3节。Connection请求响应Connection是一个比较含糊的标头字段因为它在HTTP/1.0和HTTP/1.1版本里有完全不同的用途。在HTTP/1.1版缺省情况下链接是持久的。这意味着客户端和服务器在完成请求—响应过程之后还能保持它们之间的连接有效。相反在HTTP/1.0版当客户端获取响应之后标准的做法则是关闭连接。在HTTP/1.0版在为每个请求建立连接的时候可以对Connection字段声明Keep-Alive值而在HTTP/1.1版里这是默认过程因此不必明确声明。反过来服务器或客户端都可以在请求—响应的交换结束后给Connection字段设定Close值这样就会强制关闭连接。Last-Modified响应正文Last-Modified字段提供了请求资源最后一次修改的日期和时间戳。Location响应正文Location用于让消息接收者重定向到可以找到请求资源的位置。当内容已经被转移到另一个位置时这个标头字段和状态码3xx配合使用而对于内容要根据请求的结果而创建的情况它会和状态码201配合使用。Proxy-Authorization请求这个字段和Authorization用法相同但它只适用于代理服务器。有关代理的更多信息请参见5.2.3节。Proxy-Connection请求这个字段和Connection用法相同但它只适用于代理服务器。有关代理的更多信息请参见5.2.3节。Referer请求Referer这个标头字段的用途是告诉服务器对于该资源的请求是从什么位置发出的。在上面的例子中www.rdatacollection.com/index.html会提供一个图片的链接例如/pictures/eddie.jpg。在对这个图片的请求中可以加入Referer标头字段表明用户已经在此网站上而不是从其他地点例如另一个网站来访问该图片。Server提供了关于接受了请求的服务器的信息。上面例子里的第一个服务器是基于UNIX平台上的Apache软件httpd.apache.org/而第二个服务器则是基于微软的IIS互联网信息服务Internet Information Servicewww.microsoft.com/。Set-Cookie响应Set-Cookie要求客户端保存Set-Cookie标头字段里包含的信息并在后续请求中把它作为Cookie标头字段的一部分发送回来。更深入的讲解参见Cookie部分和5.2.1节。User-Agent请求User-Agent标头字段说明了向服务器提出请求的客户端类型。这个多少有点晦涩难懂的描述可以说明用户在哪种操作系统上使用的是哪种浏览器。这个信息有助于服务器根据客户端使用的系统调整响应的内容。不过User-Agent可以包含用户自定义的任意信息例如UserAgentMy fabulous web crawler或User-AgentAll your base are belong to us。网络抓取者能够而且应该以负责任的态度使用UserAgent。我们会在5.2.1节和9.3.3节讨论如何做到这一点。Vary响应有时候服务器响应要取决于特定的参数例如取决于浏览器或客户端的设备如桌面PC或手机取决于用户之前是否访问了某个站点并获取了cookie或取决于客户端能够接受的编码格式。服务器可以通过Vary标头字段说明根据这些参数对内容进行的改动。上面的第一个例子说明响应内容会随着User-Agent、Cookie或Accept-Encoding参数的变化而不同。第二个例子则是非限定的。它声明了非限定的一组参数的改变都会导致响应的变化。该标头字段对于浏览器缓存机制是很重要的缓存机制会试图只加载新内容而从本地源查找未修改的旧内容。Via请求响应Via和Server类似但只适用于HTTP消息到达服务器或客户端所经过的代理服务器和网关。每个代理或网关可以把它的ID加到这个标头字段里这个ID通常是协议版本号加上平台类型或域名。WWW-Authenticate响应WWW-Authenticate要求客户端表明自己的身份它是和401未授权状态码一起发送的。它是Authorization请求标头字段的配对字段。WWW-Authenticate标头字段描述了确定身份的方法以及该身份的合法“范围”还有身份验证所需的更多参数。第一个例子要求进行基本身份验证而第二个例子则要求摘要身份验证这种验证方式能确保密码不会被代理所读取。我们会在5.2.2节讲解这两种类型的身份验证。[1] 如果你想学习更多传输控制协议TCP或因特网协议IP的内容Fall和Stevens2011以及Forouzan2010的相关文献都提供了这些主题的全面介绍。如需更容易理解的介绍材料可以访问https://www.netbsd.org/docs/guide/en/chap-net-intro.html。[2 ] 注意我们仅仅揭开了客户端—服务器通信技术的冰山一角。如果你需要更深入了解其后的技术例如DNS服务器是如何联系的我们建议你参阅本章的“延伸阅读”部分。[3] 我们会在5.1.2节讨论URL的结构。[4 ] 我们会在后面的内容中更深入地讲解如何监控HTTP信息交换。[5] 为了展示效果服务器响应有一些行被略去了。[6] 我们会在9.1.3节了解到从网站采集数据最简单的方式往往是查看和操作指向目标内容的URL。有时候URL会遵循一个简单的逻辑例如其中包含了一个连续的索引。这样就很容易产生一套URL可以自动地访问并保存它们的内容。[7] 我们可以利用类似http://whatismyipaddress.com/ip-lookup这样的服务来查找主机名对应的IP地址。[8] 我们可以通过声明高级搜索来指定额外的参数。要全面了解其全貌请参见http://jwebnet.net/advancedgooglesearch.html。例子里的tbsqdr:y是Google搜索语法中的一个参数具体使用方法是把它加到搜索栏URL中而不是直接在搜索框里输入。如果前面已经有了其他参数如例子中的qRCurlfiletypenote_34Apdf则需要加一个符号把它和前面的参数分开。上面例子里加上这个参数的URL是 https://www.google.com/search?qRCurlfiletype:pdftbsqdr:y——译者注[9] 回车和换行是从打字机传承下来的控制字符。在使用打字机的时候开始一个新行需要把滑动托架移回左侧并将打字盘向下移动一行。[10] 要查看这些类型的全集IANA互联网编号分配机构Internet Assigned Numbers Authority提供的清单见http://www.iana.org/assignments/media-types/media-types.xhtml。5.2 HTTP的高级特性迄今为止我们学习的仅仅是基于HTTP通信的基本知识。有更多复杂任务需要完成的功能远远超出了标准HTTP方法默认设置的能力。网络用户和服务器维护者都会问如下的问题·服务器如何能识别再次访问的用户·用户如何能避免被识别·服务器和客户端之间的通信如何能超越“无状态”也就是说它们如何能记住并依赖于之前的会话·用户如何能安全地传输和访问保密内容·用户如何能查验服务器端的内容是否有变化而无须请求内容的完整正文部分这些任务有很多是可以直接通过HTTP协议中实现的手段来处理的。我们现在要重点讲解扩展HTTP基本功能的三个领域。第一个包括了身份识别的问题这对于个性化的网络体验是很有用的。第二个领域涉及不同形式的身份验证它有助于让服务器——客户端的数据交换更加安全。第三个领域覆盖了特定类型的网络中介也就是客户端和服务器之间的中间人即代理服务器。这些领域是为多种原因例如安全性或效率而实施的。内容的获取有时会依赖于这些高级特性的运用因此关于它们的基本知识对于网络数据采集任务往往是有用的。为了展示一些高级的HTTP请求我们用到了在http://httpbin.org上的服务器。这个由Kenneth Reitz配置的服务器为HTTP请求提供了一个测试环境它会返回JSON编码的内容。这对于在把HTTP调用实施到生产环境之前进行测试是很有用的。我们利用它在R里通过RCurl命令构造一些对服务器的调用并评估它返回的消息。再进一步我们会简单介绍RCurl组件通过例子演示一些HTTP高级特性。RCurl提供了把R用作Web客户端软件的手段。该组件会在5.4节中进行更详细的介绍。