0%

爬虫原理与案例

爬虫就是一系列操作的集合,用于在互联网上代替人工从事重复性的动作,本文从0基础开始介绍爬虫的基本原理,结合案例分析爬虫的实现流程。

预备知识

在学习爬虫之前,我们首先需要熟悉和网络相关的基本知识。我们从一个最基本的例子出发。

HTTP原理

URL

URL的全称为Universal Resource Locator,即统一资源定位符,也叫网页链接,它是互联网中资源的唯一标识符。

URL的组成如图所示:

URI syntax diagram

HTTP和HTTPS

在爬虫中,我们抓取的页面通常是基于http或https协议的,因此这里首先了解一下这两个协议的含义

HTTP的全称是HypertextTransterProtocol,中文名为超文本传输协议,其作用是把超文本数据从网络传揄到本地浏览器,能够保证高效而准确地传输超文本文档。

HTTPS的全称是HypertextTransferProtocoloverSecureSocketLayer,是以安全为目标的HTTP通道,简单讲就是HTTP的安全版,即在HTTP下加人SSL层。简称HTTPS

HTTP和HTTPS协议都展于计算机网络中的应用层协议,其下层是基于TCP协议实现的,TCP协议属于计算机网络中的传输层协议,包括建立连接时的三次握手和断开时的四次挥手等过程。

HTTP请求过程

浏览器是我们上网的入口,在我们的浏览器中输入一个网址(例如https://qinxuliang1997.github.io)后,到底发生了什么?

网页浏览的过程和书信通讯的过程很相似,我们需要提供通讯方的地址(网络地址)、书信的内容(浏览器会帮我们自动生成),随后浏览器会把这个地址连同书信的内容交给快递员(网络驱动器),然后这些信息就可以在网络高速路上驰骋,最终达到收信方后,对方会根据我们的书信内容选择需要回信或者是其他动作,回信的过程和上述类似,得到了回信后浏览器根据回信的内容将信息展示在网页上。

更加具体的描述过程见:

请求

请求,英文为Request,由客户端发往服务器,分为四部分内容:请求方法(RequestMethod)请求的网址(RequestURL)、请求头(RequestHeaders)、请求体(RequestBody)。

  • 请求方法,用于标识请求客户端请求服务端的方式,常见的请求方法有两种:GET和POST。GET请求中的参数包含在URL里面,数据可以在URL中看到,而POST请求的URL不会包含这此数据,数据都是通过表单形式传输的,会包含在请求体中;GET请求提交的数据最多只有1024字节,POST方式则没有限制。
  • 请求的网址,它可以唯一确定客户端想请求的资源
  • 请求头,用来说明服务器要使用的附加信息,比较重要的信息有Host、Cookie、Referer、User-Agent、Content-Type等
  • 请求体,一般承载的内容是POST请求中的表单数据,对于GET请求,请求体为空

响应

响应,即Response,由服务器返回给客户端,可以分为三部分:响应状态码(ResponseStatusCode)响应头(ResponseHeaders)和响应体(ResponseBody)

  • 响应状态码,表示服务器的响应状态,如200代表服务器正常响应、404代表页面未找到、500代表服务器内部发生错误。
  • 响应头,包含了服务器对请求的应答信息,如Content-Type、Server、Set-Cookie等。
  • 响应体,这可以说是最关键的部分了,响应的正文数据都存在于响应体中,例如请求网页时,响应体就是网页的HTML代码:请求一张图片时,响应体就是图片的二进制数据。

Web网页基础

组成

网页可以分为三大部分: HTML、CSS和JavaScript。

HTML 定义了网页的内容和结构,CSS 描述了网页的样式,JavaScript 定义了网页的行为

  • HTML是一种用来描述网页的语言,它是网页基本的骨架和内容载体,网页通过不同类型的标签来表示不同类型的元素,如用img 标签表示图片、用 video 标签表示视频、用p 标签表示段落,这些标签之间的布局常由布局标签div 嵌套组合而成,各种标签通过不同的排列和嵌套形成最终的网页框架。

  • Css,全称叫作Cascading Style Sheets,即层叠样式表。它的作用是设置网页的样式,例如当前结构体的文字大小、颜色、间距、在页面中的位置等等;“层叠” 是指当HTML中引个几个样式文件,并且样式发生冲突时,浏览器能够按照层香顺序处理这些样式。

  • JavaScript 简称JS,是一种脚本语言,引入它的作用是为了给网页增加交互性和动态性,例如下载进度条,提示框等。

节点树

HTML的节点类型:https://www.w3schools.com/html/html_intro.asp

DOM树可视化:https://wow.techbrood.com/fiddle/29452

在HTML 中,所有标签定义的内容都是节点,这些节点构成一个HTML 节点树,也叫HTML DOM树,DOM 的最小组成单位叫做节点(node)。文档的树形结构(DOM 树),就是由各种不同类型的节点组成。每个节点可以看作是文档树的一片叶子。

节点的类型有七种。

  • Document:整个文档树的顶层节点
  • DocumentTypedoctype标签(比如<!DOCTYPE html>
  • Element:网页的各种HTML标签(比如<body><a>等)
  • Attr:网页元素的属性(比如class="right"
  • Text:标签之间或标签包含的文本
  • Comment:注释
  • DocumentFragment:文档的片段

浏览器提供一个原生的节点对象Node,上面这七种节点都继承了Node,因此具有一些共同的属性和方法。

undefined

选择器

css选择器会为不同的节点设置不同的样式规则,选择器则用于定位节点

最常用的三种方式分别是根据id.class、标签名选择。

  • 节点的id为container,那么这个节点就可以表示为#container,其中以#开头代表选择id,其后跟的是id的名称。
  • 如果想选择Class为wrapper的节点,则可以使用.wrapper,这里以.开头代表选择class,其后紧跟的是Class的名称。
  • 跟据标签名,例如想选样二级标题,直接用h2即可

css选择器还支持嵌套选择,利用空格把各个选择器分隔开便可以代表嵌套关系,如Hcontainer .wrapper p代表先选择id为container的节点,然后选择其内部class为wrapper的节点,再进一步选择该节点内部的p节点。要是各个选择器之间不加空格,则代表并列关系,如divtcontainer.wrapperp.text代表先选择id为container的div节点,然后选择其内部Class为wrapper的节点,再进一步选择这个节点内部的Class为text的p节点。

爬虫概述

什么是爬虫

网络爬虫(又被称为网页蜘蛛,网络机器人)就是模拟浏览器发送网络请求,接收请求响应,一种按照一定的规则,自动地抓取互联网信息的程序。

爬虫就是模拟浏览器的行为,越像越好,越像就越不容易被发现。

原则上,只要是浏览器(客户端)能做的事情,爬虫都能够做。

爬虫的分类:

  1. 通用爬虫:通常指搜索引擎的爬虫
  2. 聚焦爬虫:针对特定网站的爬虫

怎么实现

爬虫的流程包括四步:

  1. 获取url(列表)
  2. 请求url并获得响应
  3. 解析网页响应体获得内容
  4. 保存信息

获取网页

学习爬虫,其基本的操作便是模拟浏览器向服务器发出请求,python提供了很多功能强大的库帮助我们实现这个过程,其中最常见的就是requests,它的作用是模拟尽力模仿浏览器的一切行为,发送请求并获得服务器的响应。

最简单的例子:

1
2
3
4
5
6
7
8
9
# !pip3 install request3
import requests
r = requests.get('https://www.baidu.com/')

print(type(r)) # <class 'requeses.models.Response'>
print(r.status_code) # 200
print(type(r.text)) # <!DOCTYPE html>
print(r.text [:100]) # <!--STATUS OK--><html><head><meta http-equiv-content-type content text/html;charse
print(r.cookies) # <RequestsCookieJar[<Cookie BDORZ-27315 for .baidu.com/>]>

除了get方法外,request还支持post、put、delete、patch等方法。

在前面介绍url的构成是曾经提到url中可能会包含参数,例如:https://www.httpbin.org/get?name=germey&age=25。requests中可以使用如下的代码实现参数的传递:

1
2
3
4
5
6
7
import requests  
data = {
'name': 'germey',
'age': 25
}
r = requests.get('https://httpbin.org/get', params=data)
print(r.text)

在HTTP发起请求时,会有一个请求头Request Headers,这个头一般是浏览器自动生成的,没有这个头某些浏览器可能会检测到这不是一个正常的请求,因而导致异常。

requests中增加请求头的方式如下:

1
2
3
4
5
6
import requests
headers = {
'User-Agent’:"Mozi11a/5.0 (Macintosh; Intel Mac 05 x 10. 11_4) applenebKit/537-36 (KHTML,like Cecko) Chrome/52.0.2743.116 Safari/ 537.36'
}
r = requests.get ('https://ssr1.scrape.center/', headers=headers)
print (r.text)

除了使用get方法外,post方法也是非常常见的,它的用法如下:

1
2
3
4
import requests
data = {'name': 'germey', 'age': '25'}
r = requests.post("https://www.httpbin.org/post", data=data)
print(r.text)

提取信息

在发送请求且无误后,就会得到服务器的响应信息,这些信息包括status_code,headers等等。

我们所关心的肯定是响应体,响应体是一个HTML文本,我们所感兴趣的内容有些是直接写在HTML中,还有些可能是经过JavaScript渲染出来的,还有些可能放回的是图片、音频、视频等。

  • HTML(r.text):HTML本质上就是文本信息,在文本中提取信息最直接的方法是使用正则表达式,或者使用BeautifulSoup等专门用于内容提取的库;
  • 图片、音频、视频(r.content):这些文件本质上都是由二进制码组成的,可以将文件按照二进制的方式保存下来查看;
  • JavaScript渲染:现在越来越多的网页展现出的是JavaScript处理数据后的结果,实际和HTML中展示的不一样,这些数据可能来源自Ajax机制加载的,也可能是JavaScript和特定算法计算的等等,面对这些问题需要更加深入的探讨。

保存入库

保存信息的方式很多,简单的直接将其存在文件夹中,面对海量的数据也可能会使用数据库保存。

案例

有了上面的基本的知识,还是会发现在实际面临一个问题时候不知道从何下手,下面使用一个例子进行说明。

工具介绍

chrome开发者工具

https://zhuanlan.zhihu.com/p/47697445

分析流程

代码

进阶

Ajax

JavaScript 动态渲染页面爬取

异步编程