1.学习爬虫的好处
提升编程技能:爬虫开发需要掌握编程基础,特别是网络请求、HTML/CSS/JavaScript解析、数据存储和异常处理等技能。通过学习爬虫,你可以巩固和提升你的编程技能,特别是Python等编程语言的应用能力。
数据驱动决策:在当今数据为王的时代,数据是做出明智决策的重要依据。通过爬虫,你可以获取到各种公开的数据资源,如市场分析、用户行为、行业趋势等,从而为你的个人决策或商业决策提供有力支持。
自动化处理任务:爬虫可以实现自动化处理任务,如数据抓取、信息监控、报表生成等。这些任务如果手动完成,不仅费时费力,而且容易出错。通过学习爬虫,你可以将这些繁琐的任务自动化,提高工作效率和准确性。
增强解决问题能力:爬虫开发过程中会遇到各种挑战,如反爬虫机制、动态加载内容、验证码识别等。解决这些问题需要综合运用多种技术和方法,如分析网络请求、模拟用户行为、使用代理IP等。这些过程将锻炼你的问题解决能力和创新思维。
拓宽职业道路:爬虫技能在多个职业领域都有广泛的应用,如数据分析师、数据科学家、产品经理、市场分析师等。掌握爬虫技能将使你更具竞争力,拓宽你的职业道路和发展空间。
应对数据孤岛问题:在许多组织和企业中,数据往往分散在不同的系统和平台中,形成数据孤岛。通过学习爬虫,你可以实现不同系统之间的数据抓取和整合,打破数据孤岛,促进数据的共享和利用。
了解互联网运作机制:爬虫的工作原理涉及到网络协议、HTTP请求、服务器响应等多个方面。通过学习爬虫,你可以更深入地了解互联网的运作机制,理解网页是如何被加载和渲染的,以及数据是如何在网络中传输的。
2. HTTP协议的基本概念
全称:Hypertext Transfer Protocol(超文本传输协议)。
作用:用于从WWW服务器传输超文本到本地浏览器的传送协议,保证计算机正确快速地传输超文本文档,并确定传输文档中的哪一部分以及如何显示(如文本先于图形)。
层次:HTTP协议是应用层协议,运行于TCP/IP协议之上,通过TCP或TLS(加密的TCP连接)发送。
模型:采用客户端-服务器架构模式,客户端向服务器发送请求,服务器返回相应的响应。
2.1 HTTP协议的特点
无状态:HTTP协议对事务的处理没有记忆能力,每次请求都需要提供完整的请求信息。
无连接:HTTP协议不需要在客户端和服务器之间建立持久的连接,每个请求都是独立的,服务器处理请求后立即关闭连接(但HTTP 1.1版本支持长连接)。
面向对象:HTTP协议可以传输任何类型的数据对象,如HTML、XML、JSON、图片、音频、视频等。
无阻塞:HTTP协议不会限制客户端的请求数量和大小,使得服务器可以处理大量的请求。
可缓存:HTTP协议允许客户端缓存服务器响应的内容,以提高响应速度和减少网络流量。
2.2 HTTP协议的请求与响应
(1)请求报文
格式:请求报文由请求行、请求头部、空行和请求数据(可选)四部分组成。
请求行:包括请求方法(如GET、POST)、请求URL和HTTP协议版本信息。
请求头部:包含多个字段,用于告知服务器一些额外的信息,如客户端类型、支持的内容格式、是否支持压缩等。
(2)响应报文
格式:响应报文由状态行、响应头部、空行和响应数据(可选)四部分组成。
状态行:包括HTTP协议版本、状态码和状态信息,用于描述请求的处理结果。
响应头部:包含多个字段,用于描述响应的各种属性信息,如内容类型、内容编码、长度等。
2.3 HTTP协议的状态码
HTTP协议定义了多种不同的状态码,每个状态码都表示服务器对请求的响应状态。常见的状态码包括:
1xx(信息性状态码):表示请求已经被接收,继续处理。
2xx(成功状态码):表示请求已经被成功接收、理解和处理。
3xx(重定向状态码):表示需要进行额外操作才能完成请求。
4xx(客户端错误状态码):表示客户端发送的请求有误,服务器无法处理。
5xx(服务器错误状态码):表示服务器在处理请求的过程中发生了错误。
2.4 URI与URL
HTTP 协议使用 URI 定位互联网上的资源。因为 URI 可以访问到互联网上任意位置的资源。
URI(Uniform Resource Ide ntifier,统一资源标识符),用字符串标识某一互联网资源。
URL(Uniform Resource Locator,统一资源定位符),表示资源的地点(互联网上所处的位置)
URL是URI的一个子集,它特指那些能够定位到互联网上资源的URI。换句话说,所有的URL都是URI,但不是所有的URI都是URL。URL通常指的是能够通过网络协议访问的资源的地址。
URI 的格式:
3. 爬虫程序常用库
3.1 requests 库
requests
是 Python 中一个常用的 HTTP 请求库,通过它可以方便地发送 HTTP/1.1 请求。
它可以简化 HTTP 请求的过程,支持自动处理重定向、cookies 等功能,同时支持多种认证方式等。
3.2 requests 库基本使用
(1) 安装 requests 库
使用 requests
库,需要先安装。可以通过 pip
命令来安装:
pip install requests
(2) 导入 requests 库
安装完成后,就可以在 Python 中导入使用:
import requests
(3) requests
的常用方法
requests.get(url, params=None, **kwargs)
说明:
-
发送 GET 请求
-
url
为请求的 URL -
params
为请求参数(字典或者字符串) -
**kwargs
其它参数,如 headers、timeout 等
requests.post(url, data=None, json=None, **kwargs)
说明:
-
发送 POST 请求
-
url
为请求的 URL -
data
为 POST 请求的数据(字典或者字符串) -
json
为 POST 请求的 JSON 数据, -
**kwargs
其它参数,如 headers、timeout 等
requests.put(url, data=None, **kwargs)
说明:
-
发送 PUT 请求,
-
url
为请求的 URL -
data
为 PUT 请求的数据(字典或者字符串) -
**kwargs
其它参数,如 headers、timeout 等
requests.delete(url, **kwargs)
说明:
-
发送 DELETE 请求
-
url
为请求的 URL -
**kwargs
其它参数,如 headers、timeout 等
其中,**kwargs
为可选参数,支持以下参数:
-
headers
: 请求头部 -
cookies
: cookies -
auth
: 认证 -
timeout
: 超时时间 -
allow_redirects
: 是否允许重定向,默认为True
-
proxies
: 代理 -
verify
: 是否验证 SSL 证书,默认为True
-
cert
: SSL 证书
例:
import requests
# 发送 GET 请求
response = requests.get('https://www.baidu.com/')
print(response.status_code) # 响应状态码
print(response.text) # 响应内容
# 发送 POST 请求
data = {'key1': 'value1', 'key2': 'value2'}
response = requests.post('https://httpbin.org/post', data=data)
print(response.json()) # 响应内容(JSON 格式)
说明:
-
上述代码分别演示了使用
requests
发送 GET 和 POST 请求,获取响应状态码和内容,并将 POST 请求的数据传递给data
参数。 -
https://httpbin.org/post 是一个 HTTP 请求和响应测试网站,可以用于测试 HTTP 客户端请求的功能。你可以向该网站发送请求,然后它将返回一些关于该请求的信息,包括请求头、响应头、请求方法、请求数据等等。这对于调试和测试 HTTP 请求非常有用。
(4)处理 HTTP 响应内容
处理 HTTP 响应内容通常需要根据实际情况选择合适的方式,可以使用 requests
库提供的 text
和 content
属性获取响应内容,也可以使用其他库来处理。
(5) 获取文本内容
使用 requests
库发送 HTTP 请求并获取响应时,可以使用 text
属性来获取响应的文本内容。
例如:
import requests
response = requests.get('http://www.example.com')
print(response.text)
说明:
-
这里将请求的响应赋值给
response
变量; -
然后使用
text
属性来获取文本内容。如果响应中的内容是文本,那么这种方式非常方便,可以直接获取到文本内容进行后续处理。
(6) 获取二进制数据
如果响应中包含的是二进制数据(例如:图片、音频、视频等),那么使用 content
属性可以获取这些数据。
例如:
import requests
response = requests.get('http://www.example.com/image.jpg')
with open('image.jpg', 'wb') as f:
f.write(response.content)
说明:
-
这里将响应的二进制数据保存到本地文件中,使用了
content
属性获取响应内容。 -
需要注意的是,如果响应中包含的是二进制数据,那么不能直接使用
text
属性来获取内容,否则可能会出现编码等问题。此时应该使用content
属性获取响应内容,并根据实际需要进行进一步处理。
(7) 其他处理方式
除了使用 requests
库提供的 text
和 content
属性获取响应内容之外,还可以使用其他库来处理 HTTP 响应内容,例如:
-
BeautifulSoup
库:用于解析 HTML 和 XML 文档,可以方便地提取其中的数据。 -
lxml
库:也用于解析 HTML 和 XML 文档,性能比BeautifulSoup
更好。 -
json
库:用于解析 JSON 格式的数据。
根据实际情况选择合适的方式来处理 HTTP 响应内容,可以提高代码的可读性和可维护性。
3.3 BeautifulSoup 库基本使用
BeautifulSoup 是 Python 的一个 HTML 或 XML 解析库,可以方便地从 HTML 或 XML 文档中提取数据。
它的主要功能包括解析 HTML 或 XML 文档、搜索文档树、遍历文档树、修改文档树等。
使用 BeautifulSoup 库可以大大简化网页数据的解析和提取过程,减少爬虫代码的编写难度。
BeautifulSoup 支持多种解析器,包括 Python 自带的标准库解析器 html.parser、 lxml 解析器和 html5lib 解析器等。可以根据需要选择不同的解析器进行解析。
BeautifulSoup 对象的基本操作主要包括创建 BeautifulSoup 对象、解析 HTML 文档、搜索文档中的元素、修改 HTML 文档等。
(1)安装BeautifulSoup库
pip install BeautifulSoup4
(1) BeautifulSoup 的基本操作
BeautifulSoup(html, 'html.parser')
:将 HTML 代码解析为 BeautifulSoup 对象。
需要传入两个参数:被解析的文本和解析器。
常用的解析器有 html.parser、lxml 和 html5lib。
from bs4 import BeautifulSoup
import requests
url = 'https://www.example.com/'
response = requests.get(url)
html = response.text
soup = BeautifulSoup(html, 'html.parser')
(2) 标签选择器
在 BeautifulSoup 中,标签选择器是最常用的选择器之一,可以通过标签名直接选取指定标签。
-
soup.find('tag')
:返回第一个匹配到的标签 -
soup.find_all('tag')
:返回所有匹配到的标签 -
soup.select('css_selector')
:使用 CSS 选择器获取标签
下面是一个使用标签选择器的示例:
from bs4 import BeautifulSoup
html = """
<!DOCTYPE html>
<html>
<head>
<title>网页标题</title>
</head>
<body>
<h1>文章标题</h1>
<p>这是第一段文字</p>
<p>这是第二段文字</p>
</body>
</html>
"""
soup = BeautifulSoup(html, 'html.parser')
# 选取标题标签
title_tag = soup.title
print(title_tag)
# 选取文章标题标签
h1_tag = soup.h1
print(h1_tag)
# 选取第一段文字标签
p_tag1 = soup.p
print(p_tag1)
# 选取第二段文字标签
p_tag2 = soup.find_all('p')[1]
print(p_tag2)
输出结果如下:
<title>网页标题</title> <h1>文章标题</h1> <p>这是第一段文字</p> <p>这是第二段文字</p>
说明:
-
soup.p
选取的是第一个<p>
标签。 -
find_all
方法和列表索引的方式选取了第二个<p>
标签。 -
find
方法返回第一个匹配的标签 -
find_all
方法返回所有匹配的标签,返回结果均为一个Tag
对象。
在使用标签选择器时,需要注意标签名的大小写。例如,soup.p
可以选取<p>
标签,但无法选取<P>
标签。
同时,如果选取不存在的标签,将会返回None
类型。
(3) 标签属性选择器
-
soup.find('tag', attrs={'attribute': 'value'})
:返回第一个匹配到的带有指定属性的标签。 -
soup.find_all('tag', attrs={'attribute': 'value'})
:返回所有匹配到的带有指定属性的标签。 -
soup.select('tag[attribute=value]')
:使用 CSS 选择器获取带有指定属性的标签。
from bs4 import BeautifulSoup
html_doc = """
<html>
<head>
<title>Example</title>
</head>
<body>
<div id="content">
<p class="first">This is the first paragraph.</p>
<p class="second" custom="123">This is the second paragraph.</p>
<p class="second">This is the third paragraph.</p>
</div>
</body>
</html>
"""
soup = BeautifulSoup(html_doc, 'html.parser')
# 选择所有具有 class="second" 属性的 <p> 标签
second_paragraphs = soup.select('p[class=second]')
for p in second_paragraphs:
print(p.text)
# 选择具有 custom 属性的 <p> 标签
custom_paragraphs = soup.select('p[custom]')
for p in custom_paragraphs:
print(p.text)
(4) 获取标签内容
获取标签内容可以使用BeautifulSoup对象的.text
属性或.string
属性来获取。这两个属性可以获取标签内的纯文本内容,但有一些区别:
-
tag.text
:获取标签的纯文本内容。可以获取当前标签及其子标签内的所有文本内容,并将其拼接成一个字符串返回。使用.text
属性获取标签的文本内容非常方便,而且适用于大多数情况。 -
tag.string
:获取标签的纯文本内容。只能获取当前标签内的文本内容,当标签内含有多个字符串时,返回值为None
。 -
tag.get('attribute')
:获取标签指定属性的值。
假设有以下HTML文档:
<html>
<head>
<title>Example</title>
</head>
<body>
<h1>Hello World</h1>
<p>This is an example page.</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</body>
</html>
使用 BeautifulSoup 解析后,可以获取各个标签的内容:
from bs4 import BeautifulSoup
html_doc = """
<html>
<head>
<title>Example</title>
</head>
<body>
<h1>Hello World</h1>
<p>This is an example page.</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</body>
</html>
"""
soup = BeautifulSoup(html_doc, 'html.parser')
# 获取h1标签的文本内容
h1 = soup.find('h1')
print(h1.text) # Hello World
# 获取p标签的文本内容
p = soup.find('p')
print(p.text) # This is an example page.
# 获取ul标签的文本内容
ul = soup.find('ul')
print(ul.text) # Item 1\nItem 2\n
# 获取li标签的文本内容
li = soup.find('li')
print(li.text) # Item 1