Python用正则表达式实现爬取古诗文网站信息
作者:码农飞哥 发布时间:2021-08-30 07:12:51
分析古诗文网站
下图1展示了古诗文网站—》诗文 栏目的首页数据。该栏目的地址是:https://so.gushiwen.cn/shiwens/
第二页的地址是:https://so.gushiwen.cn/shiwens/default.aspx?page=2&tstr=&astr=&cstr=&xstr= 。依次类推第n页的地址就是page=n。其他不变。
1. 用正则表达式获取总页数
匹配的正则表达式是r'<div class="pagesright">.*?<span .*?>(.*?)</span>'
首先,r修饰的字符串是原生字符串,首先匹配到<div class="pagesright"> 标签,然后再通过.*?匹配到里面的里面的<a>标签<span>标签等。这里. 可以匹配到任意的一个字符(换行符除外),* 号可以匹配0或者任意多个字符。? 号表示只能匹配到1个或者0个。这里加上?号是为了使用非贪婪模式。
<span .*?> 通过匹配到存放总页数的<span>标签。在标签里指定.*?
(.*?) 加上() 可以指定不同的分组,这里我们只需要获取页数所以就单独添加一个分组。
所以,最终的代码是:
def get_total_pages():
resp = requests.get(first_url)
# 获取总页数
ret = re.findall(r'<div class="pagesright">.*?<span .*?>(.*?)</span>', resp.text, re.DOTALL)
result = re.search('\d+', ret[0])
for page_num in range(int(result.group())):
url = 'https://so.gushiwen.cn/shiwens/default.aspx?page=' + str(page_num)
parse_page(url)
在findall方法中传入re.DOTALL参数是为了是. 号可以匹配到换行符\n。
前面ret的结果是/ 5页。再获取5这个数字的话,还需要做一次匹配查找,这就是通过re.search('\d+', ret[0]) 来进行查找。
2. 提取诗的标题
如上图2展示了诗的标题的HTML源码,从中可以看出诗的标题被存在<b>标签 匹配诗的标题的正则表达式是<div class="cont">.*?<b>(.*?)</b>
首先还是匹配到<div class="cont"> 标签,接着就是匹配<b>(.*?)</b> 这里还是采用非贪婪模式来进行匹配。
3. 提取作者和朝代
如上图3展示了诗的作者和朝代的HTML源码,从中可以看出作者和朝代都是在<p class="source"></p> 标签下的两个a标签中。
3.1 提取作者
提取作者的正则表达式是<p class="source">.*?<a .*?>(.*?)</a> 首先还是匹配到<p class="source"> 标签。接着就是匹配第一个<a> 标签中的内容。
3.2 提取朝代
提取朝代的正则表达式是<p class="source">.*?<a .*?><a .*?>(.*?)</a> 与提取作者不同的是多了一个<a .*?> ,这是因为朝代在第二个<a>标签中。
4. 提取诗的内容
如上图4展示了诗的内容的HTML源码,从中可以看出诗句都在<div class="contson">标签中,所以只需要匹配到这个标签里的内容即可。其正则表达式是<div class="contson" .*?>(.*?)</div>。
但是这样匹配出来的数据是包含<br> 标签的。所以,我们需要通过sub 方法将这个标签替换掉。re.sub(r'<.*?>+', "", content)。
整理代码
至此,我们就将所有想要的数据都提取到了。接下来,我们还需要对数据进行处理。我们期望的最终数据格式是:
poems=[
{
"title": '渔家傲·花底忽闻敲两桨',
"author":'张三',
'dynasty':'唐朝',
'content':'xxxxxx'
}
{
"title": '鹅鹅鹅',
"author":'李四',
'dynasty':'唐朝',
'content':'xxxxxx'
}
]
前面,我们分别得到了所有标题的列表titles;所有作者的列表authors;所有朝代的列表dynastys;所有诗句的列表contents。
那么,我们如何将这些列表组合成上面的那种形式呢?
这里,就需要用到 zip 函数了。该函数可以将多个列表组合成一个新的列表,其中列表的元素是元组。比如:
a=['name','age']
b=['张三',18]
c=zip(a,b)
调用zip 方法之后得到一个zip对象,该对象可以转换成list 对象。最终得到的结果如下图5
完整源代码
# -*- utf-8 -*-
"""
@url: https://blog.csdn.net/u014534808
@Author: 码农飞哥
@File: gushiwen_rep.py
@Time: 2021/12/7 07:40
@Desc: 用正则表达式爬取古诗文网站
古诗文网站的地址:
https://www.gushiwen.cn/
"""
import re
import requests
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36'
}
first_url = 'https://so.gushiwen.cn/shiwens/default.aspx'
def get_total_pages():
resp = requests.get(first_url)
# 获取总页数
ret = re.findall(r'<div class="pagesright">.*?<span .*?>(.*?)</span>', resp.text, re.DOTALL)
result = re.search('\d+', ret[0])
for page_num in range(int(result.group())):
url = 'https://so.gushiwen.cn/shiwens/default.aspx?page=' + str(page_num)
parse_page(url)
# 解析页面
def parse_page(url):
resp = requests.get(url)
text = resp.text
# 提取标题 (.*) 进行分组,只提取<b>标签中的内容,默认情况下 .不能匹配\n。加上re.DOTALL 表示.号可以匹配所有,贪婪模式
# titles = re.findall(r'<div class="cont">.*<b>(.*)</b>', text,re.DOTALL)
# 非贪婪模式
titles = re.findall(r'<div class="cont">.*?<b>(.*?)</b>', text, re.DOTALL)
# 提取作者
authors = re.findall(r'<p class="source">.*?<a .*?>(.*?)</a>', text, re.DOTALL)
# 提取朝代
dynastys = re.findall(r'<p class="source">.*?<a .*?><a .*?>(.*?)</a>', text, re.DOTALL)
# 提取诗句
content_tags = re.findall(r'<div class="contson" .*?>(.*?)</div>', text, re.DOTALL)
contents = []
for content in content_tags:
content = re.sub(r'<.*?>+', "", content)
contents.append(content)
poems = []
for value in zip(titles, authors, dynastys, contents):
# 解包
title, author, dynasty, content = value
poems.append(
{
"title": title,
"author": author,
'dynasty': dynasty,
'content': content
}
)
print(poems)
"""
poems=[
{
"title": '渔家傲·花底忽闻敲两桨',
"author":'张三',
'dynasty':'唐朝',
'content':'xxxxxx'
}
{
"title": '渔家傲·花底忽闻敲两桨',
"author":'张三',
'dynasty':'唐朝',
'content':'xxxxxx'
}
]
"""
"""
zip 函数
a=['name','age']
b=['张三',18]
c=zip(a,b)
c=[
('name','张三'),
('age',18)
]
"""
if __name__ == '__main__':
get_total_pages()
最终的运行结果是:
来源:https://blog.csdn.net/u014534808/article/details/121764730


猜你喜欢
- 一些经常画图的开发人员大概都用过echart,不过小白用Python比较多,学习了python下的Pyecharts,发现这个包真的很强大。
- 我就废话不多说了,大家还是直接看代码吧!# -*- coding: utf-8 -*-"""Created o
- 创建一个优秀的可视化图表的关键在于引导读者,让他们能理解图表所讲述的故事。在一些情况下,这个故事可以通过纯图像的方式表达,不需要额外添加文字
- 配置Laravel 的邮件服务可以通过 config/mail.php 配置文件进行配置。邮件中的每一项都在配置文件中有单独的配置项,甚至是
- 目录一、 环境准备:1.docker环境2.安装mariadb数据库二、ORM1.ORM简介2.django配置数据库第一种方式:第二种方式
- 这篇论坛文章(赛迪网技术社区)主要介绍了一些特别有用但文档中没有介绍的sql server DBCC命令,详细内容请参考下文:以下是一些sq
- 前言昨天把自己的VASP文件处理库进行了打包并上传到PyPI,现在可以直接通过pip和easy_install来安装VASPy啦(同时欢迎使
- 本文目标:使用selenium3.0+python3操纵浏览器,打开百度网站。(相当于selenium的hello world)环境基础:p
- 前言最近很多新入职的同事问这个问题,特别是通过 homebrew 自动安装的 mysql ,其版本默认已经是 8.0 了,由于增加了一些安全
- 本文实例讲述了PHP实现的杨辉三角求解算法。分享给大家供大家参考,具体如下:♥ 前言对于 杨辉三角 是什么的问题,请参考百度百科的详细解释:
- 在 Python 中,一般情况下我们可能直接用自带的 logging 模块来记录日志,包括我之前的时候也是一样。在使用时我们需要配置一些 H
- 进程进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位,进程是一个动态概念,是程序在执行过程中分配和管理资源的基本单
- 遇到的问题:在做爬虫的时候,爬取的url链接内还有转义字符,反斜杠 \,打算用正则的re.sub()替换掉的时候遇到了问题,这是要做替换的字
- 问题:MySQL 8.0 无法远程连接访问原因:可能是mysql数据库user表中,用户的 host 字段配置是不允许当前hos
- 很久没写过东西了,今天看了chinahuman 的《用asp自动解析网页中的图片地址,并将其保存到本地服务器》,于是优化了这个程序,并且将所
- 简介Part1:写在最前 OneProxy平民软件完全自主开发的分布式数据访问层,帮助用户在MySQL/
- 有的时候我们会去扫表,然后拿出扫的结果再到另一张表里去查信息。比如下面一段index_sql_str = "select %s f
- pytorch更新完后合并了Variable与Tensortorch.Tensor()能像Variable一样进行反向传播的更新,返回值为T
- 网站中很多表单都会用到上传图片,logo,照片,用户也会上传图片,这个时候网站就需要一个上传图片的功能,而且在上传后希望能预览一下看上传的对
- goland如果当前project用了版本控制器,其下面新建的所有的项目默认都是加入到版本控制里面,所以项目名称和文件都是红色的。解决办法: