Python实战:爬取小说《盗墓笔记》
题目要求
从网页 http://www.daomubiji.com/
中可以看到《盗墓笔记》的每一本书,点开能够查看每一本书的具体内容。现在要求,保存这些内容到本地,为了看起来比较舒服,要求对每一本书新建一个文件夹,对于这本书的每一个章节,都用一个txt文件存储。
思路分析
主要思路:
1.从首页获取到 每一本书的书名和链接
2.从书的链接中获取到 每一本书的每一个章节和章节链接
3.从章节链接中获取到 正文内容
并 保存到本地
其他:
选择使用 多线程
的方法加快速度
使用XPath
的方法进行匹配
如果章节标题中有?,在本地保存中要去掉
代码实现
from threading import Thread, Lock
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
import requests
from lxml import etree
import os
# 获取结构化数据
def get_HTML(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36'}
response = requests.get(url=url, headers=headers, verify=False)
html = response.content.decode('utf-8')
tree = etree.HTML(html)
return tree
# 获取每本书的书名和链接
def get_bookinfo(url):
name_xpath = '//div[@class="sitenav"]//a/text()'
href_xpath = '//div[@class="sitenav"]//a/@href'
p = get_HTML(url)
name_list = p.xpath(name_xpath)[1:]
href_list = p.xpath(href_xpath)[1:]
return name_list, href_list
# 获取每本书的标题和标题链接
def get_chapter(url):
p = get_HTML(url)
href = p.xpath('//div[@class="excerpts"]//a/@href')
name = p.xpath('//div[@class="excerpts"]//a/text()')
return name, href
# 从每一章节中获取正文
def get_text(t_url, b_name, t_name):
# 获取对应标题链接的html
p = get_HTML(t_url)
# 从中获取对应的正文数据
content = p.xpath('//article[@class="article-content"]//p/text()')
# 如果标题中含有?
if '?' in t_name:
t_name = t_name[:len(t_name) - 1]
# 保存正文
with open(r'C:\Users\GengKY\Desktop\daomu\{}\{}.txt'.format(b_name, t_name), 'a', encoding="GBK") as f:
f.write('\n'.join(content))
print('%s %s ' % (b_name, t_name))
# 主函数
if __name__ == '__main__':
url = "http://www.daomubiji.com/"
list1, list2 = get_bookinfo(url)
theadlist = [] # 线程列表
# print(list1) #书名
# print(list2) #书的链接
for x in range(len(list1)):
# 为每本书创建一个存储用的文件夹
os.mkdir(r'C:\Users\GengKY\Desktop\daomu\{}'.format(list1[x]))
# 获取每本书的章节标题和链接
chapterlist, chapterurl = get_chapter(list2[x])
# 多线程
for y in range(len(chapterlist)):
# 多线程
thread = Thread(target=get_text, args=(chapterurl[y], list1[x], chapterlist[y]))
thread.start()
# 把线程对象都存储到 threadlist中
theadlist.append(thread)
print("所有子线程结束")
# 释放/关闭进程
for thread in theadlist:
thread.join()
print('主线程结束')