如今信息技术的发展已经进入“数据”驱动的时代,通过对海量数据的处理,能够产生极大的科研和商业价值。网络爬虫的出现,将网络上的各种数据进行自动汇总,定制化产生需要的数据,是当今时代数据获取的重要来源。网络爬虫又称网页蜘蛛、网络机器人,是一种按照一定规则、自动请求万维网网站并获取数据的程序或脚本。本系列会通过讲解网页的基本结构,然后介绍网页获取和网页解析的方法,最后通过两个综合案例,了解爬虫具体的实施过程。
Python爬虫的核心步骤大致是以下几步:发送请求、获取响应、解析内容以及保存数据。
- 发送请求:
爬虫首先需要向目标网站发送请求。这个请求通常是一个HTTP请求,它包含了请求的方法(如GET、POST等)、请求的URL、请求头(包含了一些关于请求的基本信息,如浏览器类型、用户代理等)以及请求体(如果是POST请求,这里会包含需要提交的数据)。在Python中,我们可以使用requests
库来发送HTTP请求。 - 获取响应:
当目标网站接收到请求后,它会返回一个响应。这个响应包含了状态码(表示请求是否成功)、响应头(包含了一些关于响应的基本信息,如内容类型、内容长度等)以及响应体(即网站返回的数据,通常是HTML、JSON等格式)。在Python中,requests
库会自动将响应内容保存在请求的响应对象中,我们可以通过该对象来获取响应的各种信息。 - 解析内容:
获取到响应体后,我们需要对其进行解析以提取出我们感兴趣的数据。解析的方法取决于响应体的格式。如果响应体是HTML格式,我们可以使用像BeautifulSoup
或lxml
这样的库来解析HTML并提取数据。如果响应体是JSON格式,我们可以直接使用Python的json
库来解析。 - 保存数据:
提取出数据后,我们可能需要将其保存到本地或数据库中以便后续使用。在Python中,我们可以使用文件操作来将数据保存到本地文件,也可以使用像sqlite3
或pymysql
这样的库将数据保存到数据库中。
本章的重点也就是发送请求这个过程,请求的方法(如GET、POST等)、请求的URL等,以及对输入url后的流程需要有一定的了解。
当输入URL后浏览器的简化历程:
- 解析URL:浏览器首先解析输入的URL,确定要访问的协议(如http或https、端口号、域名以及相应的路径信息等。
- DNS查询:浏览器会查询DNS(域名系统)服务器,将域名转换为与之相关联的IP地址。
- 建立TCP连接:浏览器使用解析得到的IP地址和端口号与目标服务器建立TCP(传输控制协议)连接。这通常包括一个“三次握手”过程,以确保双方都已准备好传输数据。
- 发送HTTP请求:一旦TCP连接建立,浏览器会构造一个HTTP请求报文,并通过TCP连接发送给服务器。这个请求报文中包含了请求方法(GET、POST等)、请求的URL、HTTP协议版本、请求头(可能包含浏览器类型、语言偏好、Cookie等信息)以及可能的请求体(对于POST请求)。
- 服务器处理请求:服务器接收到HTTP请求后,会根据请求的内容进行处理。这可能包括检索请求的资源(如HTML文件、图片、视频等)、运行服务器端的脚本(如PHP、Python等),以及生成动态内容。
- 返回HTTP响应:服务器处理完请求后,会构造一个HTTP响应报文并通过TCP连接发送回浏览器。响应报文中包含了HTTP状态码(如200 OK表示请求成功)、响应头(可能包含内容类型、缓存指令等信息)以及响应体(即请求的资源内容)。
- 浏览器解析和渲染:浏览器接收到HTTP响应后,会解析响应报文中的内容。如果响应体是HTML,浏览器会使用其内置的HTML解析器和CSS解析器来解析HTML文档和关联的CSS样式表,并构建DOM(文档对象模型)树和CSSOM(CSS对象模型)树。然后,浏览器会将DOM树和CSSOM树合并成一个渲染树,并根据渲染树来绘制网页内容。
- 执行JavaScript:如果网页中包含了JavaScript代码,浏览器会解析并执行这些代码。JavaScript可以修改DOM树和CSSOM树,从而改变网页的内容和样式。浏览器通常使用JavaScript引擎(如V8或SpiderMonkey)来执行JavaScript代码。
- 关闭TCP连接:当浏览器完成网页的渲染和执行JavaScript代码后,它会关闭与服务器的TCP连接(对于持久连接如Keep-Alive,连接可能会保持一段时间以便重用)。至此,输入URL后的整个流程就完成了。
这时需要注意这一过程中有一些常考的问题,例如,上述过程中涉及哪些通信协议呢?
- DNS 协议:当用户输入一个网址(如 www.baidu.com)时,浏览器首先需 要通过 DNS(域名系统)协议将域名解析为对应的 IP 地址。这个过程涉及到向 DNS 服务器发送查询请求,并由 DNS 服务器返回相应的 IP 地址。
- ARP 协议:在获取到服务器的 IP 地址后,浏览器需要与服务器建立 TCP 连 接。在此之前,浏览器需要知道服务器的 MAC 地址(物理地址)。这时,ARP (地址解析协议)就会被用来将服务器的 IP 地址解析为 MAC 地址。ARP 协议 通过广播的方式在本地网络中查询对应 IP 地址的 MAC 地址,如果找到了匹配 的 MAC 地址,就会将其缓存起来,并用于后续的通信。
- TCP/IP 协议:TCP(传输控制协议)和 IP(互联网协议)是互联网通信的基 础。在建立 TCP 连接时,会涉及到 TCP 协议的三次握手过程。一旦连接建立成 功,浏览器和服务器就可以通过 TCP 协议进行数据传输。IP 协议则负责将数据 包从源地址发送到目标地址。
- HTTP 协议:在浏览器和服务器建立连接后,浏览器会通过 HTTP(超文本 传输协议)协议向服务器发送请求,并接收服务器的响应。HTTP 协议定义了浏 览器和服务器之间的通信规则和格式。
讲完了关于网络URL请求的过程,接下来需要了解python发送请求的方法GET、POST,在python中可以使用request库来轻松发送GET和POST请求,并处理它们的响应
get | post | |
数据传递方式 | 请求的数据(如查询字符串)会附加在URL后面,并且可以被浏览器缓存和保存在历史记录中。因为数据是URL的一部分,所以它受到URL长度的限制。 | 请求的数据是在HTTP请求的主体(body)中发送的,而不是URL中。这意味着POST请求可以用来发送大量数据,并且这些数据不会出现在URL中。 |
数据安全性 | 由于数据是通过URL传递的,所以它容易被查看和记录。这使得GET方法不适合发送敏感信息(如密码)。 | 由于数据是放在HTTP消息体中发送的,相对来说更加安全,虽然仍然需要加密(如使用HTTPS)来保护数据的传输。 |
幂等性和副作用 | 是一个幂等操作,意味着多次执行相同的GET请求应该返回相同的结果,并且不应该引起服务器端状态的改变。 | 不是幂等的,意味着多次发送相同的POST请求可能会导致不同的结果(比如重复创建资源)。通常,POST请求被用于提交表单、上传文件等可能改变服务器状态的操作。 |
缓存 | 请求的结果通常会被浏览器和其他网络元素缓存,以便将来的请求可以快速获取到相同的结果。 | 请求的结果通常不会被缓存,因为POST请求往往用于提交数据,而提交的数据可能会有所不同。 |
书签和浏览器历史 | 请求的URL可以被加入书签,也可以在浏览器的历史记录中回看。 | 请求的URL虽然可以出现在地址栏中,但由于其具有副作用(可能会改变数据),因此不适合被加入书签。 |
请求体限制 | 没有请求体,数据必须放在URL的查询参数中。 | 可以使用请求体,允许发送更多类型和格式的数据(例如JSON、XML等)。 |
发送get请求(样例):
import requests
url='https://movie.douban.com/j/new_search_subjects'
header={
'User-Agent': 'Mozilla/6.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36'
}
Param={
'sort': 'U',
'range': '0,10',
'tags':'',
'start': 0
}
resp=requests.get(url,params=Param,headers=header)
print(resp.text)
发送post请求(样例):
import requests
url= "https://movie.douban.com/j/new_search_subjects"
paylod={
'i': '中国',
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'test',
'salt': 'AUTO',
'sign': 'AUTO',
'lts': 'AUTO',
'bv': 'AUTO',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'test',
'action': 'test'
}
header={
'User-Agent': 'Mozilla/6.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36'
}
resp=requests.post(url=url,data=paylod,headers=header)
print(resp.text)
发现结果中有乱码,增加charset=utf-8即可
import requests
url= "https://movie.douban.com/j/new_search_subjects"
paylod={
'i': '中国',
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'test',
'salt': 'AUTO',
'sign': 'AUTO',
'lts': 'AUTO',
'bv': 'AUTO',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'test',
'action': 'test'
}
header={
'User-Agent': 'Mozilla/6.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36',
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
}
resp=requests.post(url=url,data=paylod,headers=header)
print(resp.text)
成功完成get与post的测试