一、小小课堂
中国文学源远流长,早在远古时代,虽然文字还没有产生,但在人民中间已经流传着神话传说和民间歌谣等口头文学。随着时间线的推移,先后出现了:诗经(西周)——楚辞(战国)——乐府(汉)——赋(晋)——唐诗——宋词——元曲——明清小说。
想象一下,既然我们要更多的品味古典文学,我们是不是要专门的查看借鉴。但是又由于现在我们的时间都是零碎化的时间快,单独看书又不太现实。现如今网络如此之发达,我们每个人基本上都已经离不开电脑、手机了。那么我们可不可以通过Python爬虫的方式,把这些内容全不爬取出来,然后通过电子设备进行阅读呢?
下面就开始实现此设想。
二、网页分析
从理想到现实的第一步,当然是先找到网站了。
古诗文网:https://www.gushiwen.org/
我们打开网址之后,发现网页如下:
2.1 确定要爬取的内容对应的url
我们先查看网页的结构
代码:
start_url = "https://so.gushiwen.cn/shiwen/"base_url = "https://so.gushiwen.cn"12
2.2 分析抓取的主要内容
根据上述两图我们先确定爬取的内容: 一级类型,二级类型,诗词名称,诗词作者,诗词内容,诗词译文及注释
2.3 获取所有的一级类型(错误版本)
import requestsfrom lxml import etree
start_url = "https://so.gushiwen.cn/shiwen/"base_url = "https://so.gushiwen.cn"headers = {
"user-agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",}items = []def parse_url(url):
"""解析url,得到响应内容"""
# time.sleep(random.random())
response = requests.get(url=url, headers=headers)
return response.content.decode("utf-8")def parse_html(html):
"""使用xpath解析html,返回xpath对象"""
etree_obj = etree.HTML(html)
return etree_obj
html = parse_url(start_url)etree_obj = parse_html(html)first_type_name_list = etree_obj.xpath('//div[@class="cont"]/a/text()')first_type_url_list = etree_obj.xpath('//div[@class="cont"]/a/@href')print(first_type_name_list)print(first_type_url_list)1234567891011121314151617181920212223242526272829303132
4. 结果
不知道,同学们有没有发现此处有问题呢?
2.4 获取所有的一级类型(修改版本)
我们上述的解析式其实是有问题的,它是吧所有的包括作者也解析出来了,看下图:
正确的写法是这样的
first_type_name_list = etree_obj.xpath('(//a[contains(@href,"/gushi/")]|//a[contains(@href,"/wenyan/")])/text()')first_type_url_list = etree_obj.xpath('(//a[contains(@href,"/gushi/")]|//a[contains(@href,"/wenyan/")])/@href')12
2.5 获取二级标题
1. 解析
2. 代码
#二级类型类型数据div
for div in div_list:
#二级类型名称
second_type_name = div.xpath(".//strong/text()")
if second_type_name: # 有的没有二级类型
second_type_name = second_type_name[0]
else:
second_type_name = ""
print(second_type_name)123456789
3. 结果
2.6 获取二级类型下诗词的名称和url
1. xpath解析
2. 代码
#二级类型下诗词的名称和url
poetry_name_list = div.xpath(".//span/a/text()")
poetry_url_list = div.xpath(".//span/a/@href")
data_zip = zip(poetry_name_list,poetry_url_list)1234
2.7 查询数据
2.7.1 拼接URL
查询数据的话,首先我们先拼接一级URL
#一级类型url
url = base_url + first_type["url"]
print(url)
first_type_name = first_type["name"]
print(first_type_name)12345
for data in data_zip:
#item是一个诗词数据
item = {}
item["first_type_name"] = first_type_name
item["second_type_name"] = second_type_name
item["poetry_name"] = data[0]
#诗词url
poetry_url = base_url+data[1]
print(poetry_url)123456789
2.7.2 内容解析
1. xpath解析
1.诗词名称
2.诗词作者
3.诗词内容
4.诗词译文及注释
2. 代码实现
#诗词作者
poetry_author = etree_obj.xpath('//p[@class="source"]')[0].xpath(".//text()")
item["poetry_author"] = "".join(poetry_author).strip()
#诗词内容
poetry_content = etree_obj.xpath('//*[@id="contson45c396367f59"]/text()')
item["poetry_content"] = "".join(poetry_content).strip()
#诗词译文和注释
if etree_obj.xpath('//div[@class="contyishang"]'):#有的没有注释
poetry_explain = etree_obj.xpath('//div[@class="contyishang"]')[0].xpath(".//text()")
item["poetry_explain"] = "".join(poetry_explain).strip()
else:
item["poetry_explain"] = ""
print(item)12345678910111213
为什么会加上判断语句,是因为网站有反爬机制,通过加上判断机制,才能够正常的循环爬取。
3. 运行结果
三、完整代码
# encoding: utf-8'''
@author 李华鑫
@create 2020-10-08 9:42
Mycsdn:https://buwenbuhuo.blog.csdn.net/
@contact: 459804692@qq.com
@software: Pycharm
@file: 古诗词.py
@Version:1.0
'''"""
https://www.gushiwen.cn/
https://so.gushiwen.cn/shiwen/
"""import requestsimport timeimport randomimport csvfrom lxml import etree
start_url = "https://so.gushiwen.cn/shiwen/"base_url = "https://so.gushiwen.cn"headers = {
"user-agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",}items = []def parse_url(url):
"""解析url,得到响应内容"""
# time.sleep(random.random())
response = requests.get(url=url, headers=headers)
return response.content.decode("utf-8")def parse_html(html):
"""使用xpath解析html,返回xpath对象"""
etree_obj = etree.HTML(html)
return etree_objdef get_first_type():
"""获取所有的一级类型"""
first_type_list = []
html = parse_url(start_url)
etree_obj = parse_html(html)
first_type_name_list = etree_obj.xpath('(//a[contains(@href,"/gushi/")]|//a[contains(@href,"/wenyan/")])/text()')
first_type_url_list = etree_obj.xpath('(//a[contains(@href,"/gushi/")]|//a[contains(@href,"/wenyan/")])/@href')
data_zip = zip(first_type_name_list, first_type_url_list)
for data in data_zip:
first_type = {}
first_type["name"] = data[0]
first_type["url"] = data[1]
first_type_list.append(first_type)
return first_type_listdef get_data(first_type):
"""查询数据"""
#一级类型url
url = base_url + first_type["url"]
first_type_name = first_type["name"]
#向一级类型url发送请求获取二级类型数据
html = parse_url(url)
etree_obj = parse_html(html)
div_list = etree_obj.xpath('//div[@class="typecont"]')
#二级类型类型数据div
for div in div_list:
#二级类型名称
second_type_name = div.xpath(".//strong/text()")
if second_type_name: # 有的没有二级类型
second_type_name = second_type_name[0]
else:
second_type_name = ""
#二级类型下诗词的名称和url
poetry_name_list = div.xpath(&q
四、保存结果
转载自:CSDN 作者:不温卜火
原文链接:https://buwenbuhuo.blog.csdn.net/article/details/109306251