一、网络爬虫概述
1.1 什么是网络爬虫
网络爬虫(Web Crawler),也称网络机器人,是一种按照预设规则,自动浏览互联网并抓取网页数据的程序或脚本。它模拟人类浏览网页的行为,但效率极高,可以在短时间内遍历成千上万个页面。
爬虫的核心工作流程可以概括为四个步骤:
-
开始:设定起始URL和抓取规则
-
发送HTTP请求:向目标服务器请求页面内容
-
解析结果提取数据:从HTML文档中抽取出所需信息
-
数据处理与存储:清洗、整理并保存数据
1.2 爬虫的应用场景
爬虫技术广泛应用于多个领域:
-
搜索引擎(如百度、Google)------抓取网页建立索引,支撑亿万级检索
-
舆情监控------实时监测社交媒体、新闻网站的舆论动态
-
商业分析(如电商比价系统)------采集商品价格、评论,辅助决策
-
AI大模型训练------收集海量文本语料,用于模型预训练
可以说,在大数据时代,爬虫是获取外部数据不可或缺的工具。
1.3 爬虫的合规性------robots协议

在编写爬虫之前,必须了解 robots协议 (也称爬虫协议、君子协议)。该协议是网站根目录下存放的 robots.txt 文本文件,用于告知爬虫哪些页面允许抓取,哪些禁止抓取。
下面以知名编程语言排行榜网站 TIOBE 的 robots.txt 为例:
User-agent: *
Disallow: /wp-admin/
Allow: /wp-admin/admin-ajax.php
Sitemap: https://www.tiobe.com/sitemap_index.xml
Crawl-delay: 5
User-agent: Wandoujia Spider
Disallow: /
User-agent: Mediapartners-Google
Disallow: /subject_search
Disallow: /amazon_search
关键字段含义:
-
User-agent:标识爬虫身份(*表示所有爬虫) -
Disallow:禁止访问的资源路径 -
Allow:允许访问的资源路径 -
Sitemap:网站地图地址,帮助爬虫发现页面 -
Crawl-delay:请求间隔时间(秒),避免对服务器造成压力
请务必遵守 robots.txt 的约定,这是爬虫开发者基本的职业道德。虽然它是"君子协议"而非法律强制,但遵守它既是尊重网站所有者,也是保护自己免受法律风险。
二、入门程序:发送HTTP请求
2.1 安装 requests 库
Python 中最流行的 HTTP 客户端库是 requests,它让发送网络请求变得极其简单。安装命令:
pip install requests
2.2 发送请求获取网页
我们以获取 TIOBE 编程语言排行榜页面为例:
import requests
url = "https://www.tiobe.com/tiobe-index/"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
response = requests.get(url, headers=headers)
print(response.status_code) # 200 表示成功
print(response.text[:500]) # 打印前500字符的HTML
关键点:
-
requests.get()发送 GET 请求 -
headers参数设置 User-Agent,模拟浏览器访问,避免被识别为爬虫 -
response.text返回服务器响应的 HTML 源代码
仅需几行代码,我们就成功获取了网页的完整内容,为后续解析提供了原始素材。
三、网页结构基础
3.1 网页的三部分:HTML、CSS、JS
一个网页由三个核心技术共同构成:
| 组成部分 | 全称 | 作用 |
|---|---|---|
| HTML | 超文本标记语言 | 负责网页的结构(页面元素和内容) |
| CSS | 层叠样式表 | 负责网页的表现(样式、颜色、位置、大小) |
| JS | JavaScript | 负责网页的行为(交互效果、动态更新) |
这三者各司其职:HTML 搭建骨架,CSS 美化外观,JS 赋予生命力。
3.2 HTML 基本语法
HTML(HyperText Markup Language)是一种超文本标记语言 。"超文本"意味着它不仅包含文字,还可以定义图片、音频、视频等内容。"标记语言"则是指由一堆预定义的标签构成,如 <h1>、<p>、<a> 等。
一个简单的 HTML 示例:
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>仙逆人物志 - 修真世界</title>
</head>
<body>
<h1>Python</h1>
<p>一门简洁、快速、易用的编程语言。</p>
<a href="https://www.itcast.cn">传智教育-黑马程序员</a>
</body>
</html>
标签规则:
-
标签通常成对出现:
<标签名>内容</标签名>(开始标签 + 结束标签) -
标签可以拥有属性 ,如
<a href="...">中的href指定链接地址 -
HTML 代码直接在浏览器中运行,由浏览器解析并渲染
爬虫的核心任务就是从这些标签的海洋中,精准定位并提取我们需要的数据。
四、网页解析:XPath 与 lxml
4.1 什么是网页解析
网页解析是指从原始 HTML 文档中提取数据的过程,也是网络爬虫的关键步骤。我们需要从一堆标签和文本中,抽取出目标信息(如标题、价格、评分等)。
4.2 安装 lxml 库
lxml 是 Python 中高性能的 HTML/XML 解析库,支持基于 XPath 语法来解析和提取网页数据。安装命令:
pip install lxml
4.3 XPath 语法详解

XPath(XML Path Language)是一种在 HTML/XML 文档中导航定位元素的查询语言,能让你准确地定位文档中的特定元素、属性或文本。
常见 XPath 表达式及含义:
| XPath 表达式 | 含义 |
|---|---|
/html/head/title[1] |
选择 <html> 下 <head> 中的第一个 <title> 元素 |
//div/a/text() |
选择文档中所有 <div> 下的 <a> 标签的文本内容 |
//div/a/@href |
选择所有 <div> 下的 <a> 标签的 href 属性值 |
//div/a[@target='_blank'] |
选择所有 target 属性值为 _blank 的 <a> 标签 |
//div[2]/p[last()]/text() |
选择第二个 <div> 下最后一个 <p> 标签的文本 |
要点:
-
/表示从根节点开始(绝对路径) -
//表示在文档任意位置搜索(相对路径) -
[ ]用于添加条件(索引、属性筛选等) -
text()提取标签内的文本 -
@属性名提取标签的属性值
4.4 使用 lxml 提取数据
from lxml import html
# 加载HTML文件
with open("resources/仙逆人物志.html", "r", encoding="utf-8") as f:
html_content = f.read()
# 解析为文档对象
doc = html.fromstring(html_content)
# 使用XPath提取数据
th_list = doc.xpath("//table/thead/tr[1]/th/text()")
td_list = doc.xpath("//table/tbody/tr[1]/td/text()")
print("表头:", th_list)
print("第一行数据:", td_list)
html.fromstring() 将 HTML 字符串解析为可执行 XPath 查询的文档对象,然后通过 xpath() 方法直接提取目标数据,返回列表。
五、案例实战:获取高分电影榜单
5.1 案例目标与步骤
本案例的目标是从 The Movie Database (TMDB) 获取高分电影 Top100 数据,并保存为 CSV 文件。
需要提取的字段包括:
-
电影名、年份、上映时间、类型、时长、评分、语言
-
导演、作者、主演、Slogan、简介
实现步骤如下:
-
查看目标网站的
robots.txt,确认抓取规则 -
分析页面结构,确定数据在 HTML 中的位置
-
获取电影列表页,提取每部电影的详情页链接
-
遍历每一部电影的详情页,提取全部所需字段
-
对提取到的原始数据进行清洗(如处理年份、时长格式)
-
将清洗后的数据写入 CSV 文件
5.2 数据清洗------正则表达式
在实际抓取中,原始数据往往不够"干净"。例如:
-
年份字段可能是
1994、1994-09-23或1994 (USA) -
时长可能是
144 分钟、2h 24min或144 -
评分可能包含多余字符
我们需要从中提取出纯净的数字或标准格式。这时就要用到正则表达式(Regular Expression)。
正则表达式是一种用特定语法规则组成的字符串模式,用来描述、匹配或替换文本中符合某种规则的字符序列。可以理解为专门用于文本处理的"高级查找和匹配公式"。
Python re 模块三大函数
| 函数 | 作用 |
|---|---|
match(pattern, string) |
从字符串开头开始匹配 |
search(pattern, string) |
从任意位置搜索第一个匹配项 |
findall(pattern, string) |
从任意位置搜索所有匹配项,返回列表 |
注意 :字符串前的 r 表示原始字符串,使转义字符无效,如 r"\d" 就是反斜杠和 d 两个字符,而非转义。
5.3 正则表达式语法速查
| 语法 | 含义 |
|---|---|
. |
匹配任意单个字符(除换行符) |
\d |
匹配数字,\D 匹配非数字 |
\w |
匹配字母、数字、下划线,\W 匹配非单词字符 |
\s |
匹配空白字符,\S 匹配非空白 |
* |
匹配前一个字符 0次或多次 |
+ |
匹配前一个字符 1次或多次 |
? |
匹配前一个字符 0次或1次 |
{m} |
匹配前一个字符 恰好 m 次 |
{m,} |
匹配前一个字符 至少 m 次 |
{m,n} |
匹配前一个字符 m 到 n 次 |
| ` | ` |
() |
分组,捕获子表达式 |
^ |
匹配字符串开头 |
$ |
匹配字符串结尾 |
实用示例:
-
匹配手机号:
1[3-9]\d{9}(1开头,第二位3-9,后面9位数字) -
匹配年份:
\d{4}(四位数字) -
提取数字:
\d+(一个或多个数字)
5.4 完整代码实现
下面给出案例的核心代码框架,实际项目中需根据页面结构调整 XPath。
import requests
from lxml import html
import csv
import re
# 目标网站(请先查看其 robots.txt)
BASE_URL = "https://www.themoviedb.org"
LIST_URL = BASE_URL + "/top-rated"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
# 1. 获取列表页
resp = requests.get(LIST_URL, headers=headers)
doc = html.fromstring(resp.text)
# 2. 提取每部电影的详情页链接(假设链接在 class='title' 的 a 标签的 href 属性中)
movie_links = doc.xpath("//a[@class='title']/@href")
all_movies = []
# 3. 遍历前100部电影
for link in movie_links[:100]:
detail_url = BASE_URL + link
detail_resp = requests.get(detail_url, headers=headers)
detail_doc = html.fromstring(detail_resp.text)
# 4. 提取各字段(以下 XPath 仅为示例,需根据实际页面调整)
title = detail_doc.xpath("//h2[@class='title']/text()")[0] if detail_doc.xpath("//h2[@class='title']/text()") else ""
# 年份处理:提取四位数字
raw_year = detail_doc.xpath("//span[@class='year']/text()")[0] if detail_doc.xpath("//span[@class='year']/text()") else ""
year = re.search(r"\d{4}", raw_year).group() if re.search(r"\d{4}", raw_year) else ""
# 时长处理:提取数字
raw_runtime = detail_doc.xpath("//span[@class='runtime']/text()")[0] if detail_doc.xpath("//span[@class='runtime']/text()") else ""
runtime = re.search(r"\d+", raw_runtime).group() if re.search(r"\d+", raw_runtime) else ""
# 评分
rating = detail_doc.xpath("//span[@class='rating']/text()")[0] if detail_doc.xpath("//span[@class='rating']/text()") else ""
# 其他字段(导演、主演等)类似处理...
# 5. 收集数据
all_movies.append([title, year, runtime, rating]) # 仅示例,实际要包含全部字段
# 6. 写入CSV文件
with open("top100_movies.csv", "w", encoding="utf-8", newline="") as f:
writer = csv.writer(f)
writer.writerow(["电影名", "年份", "时长(分钟)", "评分"]) # 表头
writer.writerows(all_movies)
print(f"成功抓取 {len(all_movies)} 部电影数据,已保存到 top100_movies.csv")
CSV 说明:CSV(Comma-Separated Values,逗号分隔值)是一种简单通用的文本文件格式,用于存储表格数据,可直接用 Excel 打开。
六、总结
通过本文,我们系统学习了:
-
爬虫的基本概念与应用场景
-
robots.txt 君子协议及其关键字段
-
requests 库发送 HTTP 请求
-
HTML/CSS/JS 网页结构与标签语法
-
XPath 与 lxml 解析网页并提取数据
-
正则表达式进行文本清洗与格式化
-
一个完整的电影榜单爬取案例(从列表到详情,再到 CSV 存储)
爬虫是数据获取的重要手段,但也是一把双刃剑。在实际开发中,请牢记:
-
遵守 robots.txt,尊重网站规则
-
控制请求频率,设置合理的间隔(如 Crawl-delay),避免给服务器造成负担
-
合理使用数据,不侵犯他人权益
-
动态反爬 是常见挑战,后续可学习 Selenium、代理IP、异步请求等进阶技术
技术无好坏,但使用技术的人要有底线。愿你在爬虫的世界里,既收获数据,也守住道德。
Happy Coding!🐍
Happy Coding!🐍
Happy Coding!🐍