如何用正则表达式爬取古诗文网中的数据(python爬虫)
一、了解正则表达式的基本内容:
什么是正则表达式
正则表达式(Regular Expression,简称 regex)是一种用于匹配字符串的模式。它通过特定的语法规则,可以高效地搜索、替换和提取文本中的特定内容。正则表达式广泛应用于文本处理、数据验证、日志分析等领域。
正则表达式在爬虫中的应用
在爬虫中,正则表达式主要用于从网页源码中提取所需信息。以下是其主要应用场景:
-
数据提取:
-
从HTML中提取特定标签的内容,如链接、标题、图片地址等。
-
示例:提取所有链接:
<a\s+(?:[^>]*?\s+)?href="([^"]*)"
-
-
数据清洗:
-
去除多余的空格、换行符或HTML标签。
-
示例:去除HTML标签:
<[^>]+>
-
-
数据验证:
-
验证提取的数据是否符合预期格式,如邮箱、日期等。
-
示例:验证邮箱:
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
-
-
URL匹配:
-
匹配特定模式的URL,用于过滤或分类。
-
示例:匹配图片URL:
https?://[^\s]+?\.(jpg|png|gif)
-
正则表达式的核心知识点
-
基本语法:
-
字符匹配:普通字符匹配自身,如
a
匹配字符 "a"。 -
元字符:具有特殊含义的字符,如
.
匹配任意字符,*
匹配前一个字符的零次或多次。
-
-
字符类:
-
[abc]
匹配 "a"、"b" 或 "c"。 -
[^abc]
匹配除 "a"、"b"、"c" 之外的字符。 -
\d
匹配数字,\w
匹配字母、数字或下划线,\s
匹配空白字符。
-
-
量词:
-
*
:零次或多次。 -
+
:一次或多次。 -
?
:零次或一次。 -
{n}
:恰好 n 次。 -
{n,}
:至少 n 次。 -
{n,m}
:n 到 m 次。
-
-
分组和捕获:
-
(abc)
匹配 "abc" 并捕获。 -
(?:abc)
匹配 "abc" 但不捕获。
-
-
锚点:
-
^
匹配字符串开头。 -
$
匹配字符串结尾。 -
\b
匹配单词边界。
-
-
贪婪与懒惰匹配:
-
默认是贪婪匹配,尽可能匹配更多字符。
-
在量词后加
?
可进行懒惰匹配,尽可能匹配更少字符。 -
示例:
a.*?b
匹配 "a" 和 "b" 之间的最短内容。
-
总结
正则表达式是爬虫中强大的工具,能够高效提取和清洗数据。掌握其基本语法和常用技巧,能显著提升爬虫的开发效率和数据处理能力。
同时代码中还涉及到了re库的使用:
re
是 Python 标准库中用于处理正则表达式的模块,提供了丰富的函数和方法来操作字符串。通过 re
库,你可以轻松实现字符串的匹配、查找、替换和分割等操作。
re
库是 Python 中处理正则表达式的强大工具,提供了多种函数和方法来操作字符串。掌握 re
库的使用,可以显著提升文本处理的效率和灵活性,尤其在爬虫开发中,re
库是不可或缺的工具。
re
库的核心功能
-
编译正则表达式:
-
re.compile(pattern, flags=0)
:将正则表达式编译成一个正则对象,便于重复使用。 -
示例:
pattern = re.compile(r'\d+')
-
-
匹配字符串:
-
re.match(pattern, string, flags=0)
:从字符串开头匹配正则表达式,返回匹配对象或None
。 -
示例:
match = re.match(r'\d+', '123abc') if match: print(match.group()) # 输出: 123
-
-
搜索字符串:
-
re.search(pattern, string, flags=0)
:在字符串中搜索第一个匹配项,返回匹配对象或None
。 -
示例:
search = re.search(r'\d+', 'abc123def') if search: print(search.group()) # 输出: 123
-
-
查找所有匹配项:
-
re.findall(pattern, string, flags=0)
:返回所有匹配项的列表。 -
示例:
findall = re.findall(r'\d+', 'a1b2c3') print(findall) # 输出: ['1', '2', '3']
-
-
查找所有匹配项(返回迭代器):
-
re.finditer(pattern, string, flags=0)
:返回所有匹配项的迭代器,每个元素是一个匹配对象。 -
示例:
finditer = re.finditer(r'\d+', 'a1b2c3') for match in finditer: print(match.group()) # 输出: 1, 2, 3
-
-
替换字符串:
-
re.sub(pattern, repl, string, count=0, flags=0)
:替换字符串中所有匹配项,返回替换后的字符串。 -
示例:
sub = re.sub(r'\d+', 'X', 'a1b2c3') print(sub) # 输出: aXbXcX
-
-
分割字符串:
-
re.split(pattern, string, maxsplit=0, flags=0)
:根据正则表达式分割字符串,返回列表。 -
示例:
split = re.split(r'\d+', 'a1b2c3') print(split) # 输出: ['a', 'b', 'c', '']
-
re
库的常用方法详解
-
匹配对象的方法:
-
group()
:返回匹配的字符串。 -
start()
:返回匹配的起始位置。 -
end()
:返回匹配的结束位置。 -
span()
:返回匹配的 (起始, 结束) 位置元组。
-
-
编译标志:
-
re.IGNORECASE
或re.I
:忽略大小写。 -
re.MULTILINE
或re.M
:多行模式,^
和$
匹配每行的开头和结尾。 -
re.DOTALL
或re.S
:.
匹配包括换行符在内的所有字符。 -
re.VERBOSE
或re.X
:允许在正则表达式中添加注释和空白符。
-
二、具体的爬虫代码解释(以古诗文网为例)
古诗文网-古诗文经典传承
url=唐代诗文_古诗文网https://www.gushiwen.cn/shiwens/default.aspx?cstr=%e5%94%90%e4%bb%a3 (以唐代的诗文题目为例,可扩充)
右键检查 :
具体的代码解释 :
1. requests
库的使用
-
功能:
requests
是一个用于发送 HTTP 请求的 Python 库,常用于爬虫中获取网页内容。 -
知识点:
-
requests.get(url, headers=headers)
:发送 GET 请求,获取网页内容。 -
resp.encoding = 'utf-8'
:设置响应的编码格式,确保正确解析中文内容。 -
resp.text
:获取响应的文本内容(HTML 源码)。 -
headers
:请求头,用于模拟浏览器访问,避免被网站反爬虫机制拦截。-
User-Agent
:标识客户端类型(如浏览器),示例中使用的是 Chrome 浏览器的标识。
-
-
2. 正则表达式(re
库)
-
功能:用于从 HTML 文本中提取目标数据(如古诗标题)。
-
知识点:
-
re.findall(pattern, string, flags)
:从字符串中查找所有匹配正则表达式的部分,返回一个列表。 -
正则表达式模式:
-
r'<div\sclass="cont">.*?<b>(.*?)</b>'
:-
<div\sclass="cont">
:匹配<div class="cont">
标签。 -
.*?
:非贪婪匹配任意字符(尽可能少匹配)。 -
<b>(.*?)</b>
:匹配<b>
标签中的内容,(.*?)
是捕获组,提取标题内容。
-
-
-
re.DOTALL
标志:使.
匹配包括换行符在内的所有字符。
-
3. Python 函数
-
功能:将代码模块化,提高可读性和复用性。
-
知识点:
-
def parse_page(url)
:定义一个函数,用于解析网页内容。 -
def spider()
:定义一个函数,作为爬虫的入口。 -
if __name__ == '__main__':
:确保脚本在直接运行时执行spider()
函数,而在被导入时不执行。
-
4. URL 和请求头
-
知识点:
-
URL:
-
https://www.gushiwen.cn/shiwens/default.aspx?cstr=%e5%94%90%e4%bb%a3
:目标网页地址。 -
cstr=%e5%94%90%e4%bb%a3
:URL 编码,表示查询参数(这里是“唐代”)。
-
-
请求头:
-
headers
:用于模拟浏览器访问,避免被反爬虫机制拦截。 -
User-Agent
:标识客户端类型,示例中使用的是 Chrome 浏览器的标识。
-
-
5. 编码问题
-
知识点:
-
resp.encoding = 'utf-8'
:设置响应的编码格式为 UTF-8,确保正确解析中文内容。 -
如果未设置编码,可能会导致乱码问题。
-
6. 代码执行流程
-
知识点:
-
调用
spider()
函数。 -
spider()
函数调用parse_page(url)
,传入目标 URL。 -
parse_page(url)
发送 HTTP 请求,获取网页内容。 -
使用正则表达式从 HTML 中提取古诗标题。
-
打印提取的标题列表。
-
具体代码展示:
import requests
import re
url = "https://www.gushiwen.cn/shiwens/default.aspx?cstr=%e5%94%90%e4%bb%a3"
header = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0"
}
def parse_page(url):
resp = requests.get(url, headers=header)
resp.encoding = 'utf-8' # 确保编码正确
html = resp.text
# 调整正则表达式以匹配实际的HTML结构
titles = re.findall(r'<div\sclass="cont">.*?<b>(.*?)</b>', html, re.DOTALL)
print(titles)
def spider():
url = "https://www.gushiwen.cn/shiwens/default.aspx?cstr=%e5%94%90%e4%bb%a3" # 古诗文网
parse_page(url)
if __name__ == '__main__':
spider()
运行结果:
三、改进建议:根据以上代码格式不光可以爬取古诗文题目也可以爬取内容作者等
所以后面的代码有改动:
import requests
import re
# 目标URL
url = "https://www.gushiwen.cn/shiwens/default.aspx?cstr=%e5%94%90%e4%bb%a3"
# 请求头,模拟浏览器访问
header = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0"
}
def parse_page(url):
# 发送HTTP请求,获取网页内容
resp = requests.get(url, headers=header)
resp.encoding = 'utf-8' # 设置编码
html = resp.text
# 正则表达式提取古诗的标题、作者和内容
poem_pattern = re.compile(
r'<div class="cont">.*?<b>(.*?)</b>.*?' # 标题
r'<p class="source">.*?<a.*?>(.*?)</a>.*?<a.*?>(.*?)</a>.*?' # 作者
r'<div class="contson".*?>(.*?)</div>', # 内容
re.DOTALL
)
# 查找所有匹配的古诗
poems = poem_pattern.findall(html)
# 遍历提取结果
for poem in poems:
title = poem[0].strip() # 标题
author = f"{poem[1].strip()} {poem[2].strip()}" # 作者
content = re.sub(r'<.*?>', '', poem[3]).strip() # 去除内容中的HTML标签
# 打印结果
print(f"标题: {title}")
print(f"作者: {author}")
print(f"内容: {content}")
print("-" * 50) # 分隔线
def spider():
# 目标URL
url = "https://www.gushiwen.cn/shiwens/default.aspx?cstr=%e5%94%90%e4%bb%a3"
parse_page(url)
if __name__ == '__main__':
spider()
部分正则表达式的来源:
poem_pattern = re.compile(
r'<div class="cont">.*?<b>(.*?)</b>.*?' # 标题
r'<p class="source">.*?<a.*?>(.*?)</a>.*?<a.*?>(.*?)</a>.*?' # 作者
r'<div class="contson">.*?>(.*?)</div>', # 内容
re.DOTALL
)
运行结果: