python爬虫——爬取小说(以晋江文学网为例)
前言
大创组员在学习python
,2020年的大创项目需要用python
获取百度迁徙网站上的数据,
因此需要让她们学会爬虫。因此这是使用晋江文学网为例的一个爬虫小练习。
对于刚学python
没多久的她们,想要接触完全陌生的爬虫,必然是存在一些困难的。
此外还缺少网页开发(html
)的基础,因此对于许多部分必定存在疑惑,因此在此记录一下简单爬虫的流程与笔记。
此外,由于python
实在是博大精深,若想要从头开始学习,则时间不够充分,因此这里采用逆向角度,
从实际应用的角度逆向来学习python
。在学习爬虫的时候也是一样,直接从源代码开始入手,
找到一个可以运行的代码,然后看懂它是如何运作的,记录自己不会的地方,并查明然后做笔记记录下来。
注:学习方法并无对错之分,只有适合于不适合。
学习流程
百度搜一篇爬小说带源代码的博客
将源代码复制下来到
pycharm
,修改保存路径(若有)运行代码,若失败则尝试修复,修复不了,换博客
执行成功,则开始分析源代码
找出作者爬取小说的思路
修改相应部分,改成自己所需的网址和保存格式
源代码思路
- 用
python
打开小说网址,找到小说章节列表 - 获取小说章节标题,章节Url,组成章节列表
- 遍历章节列表,打开小说章节网址
- 获取小说正文内容
- 在指定文件夹中,创建以章节标题为名字的文本文档
- 在对应文档中,写入小说内容
- 关闭对应文档
思路解析
用
python
打开小说网址,找到小说章节列表 a. 网页由主要内容由html
文件呈现,则只需获取html
文件内容 b. 单纯获取html
内容,无需登录等需要输入信息的操作,因此为Get
请求 c. 使用requests
库,Get请求只需几行代码。获取小说章节标题,章节Url,组成章节列表 a. 获取到的
html
文件内容,由一系列标签
(html
代码术语)组成,因此需要找到小说章节标题与Url所在标签 b. 使用beautifulSoup
库,简单,迅速,便捷,容错性高。使用
python
内置对象创建文本文档open()
函数,用于创建和打开一个file
对象
Tip:标签
:html
语言术语,由'<>'包含的叫做标签
,例如:< div>xxx</ div>;< a>xxx</ a>;< span>xxx</ span>;< p>xxx</ p>(xxx为网页内容)
源代码
601from bs4 import BeautifulSoup
2import time
3import requests
4
5
6# 访问url,返回html页面
7def get_html(url):
8 r = requests.get(url)
9 r.raise_for_status()
10 r.encoding = r.apparent_encoding
11 return r.text
12
13
14# 从列表页获取小说章节名和链接
15def get_chapters(url): # 根据列表页,返回此页的{书名:链接}的字典
16 html = get_html(url)
17 soup = BeautifulSoup(html, 'lxml')
18 temp_lists = soup.find_all('a', attrs={'itemprop': 'url'})
19 chapter_dict = {}
20 for chapter in temp_lists:
21 temp_name = chapter.get_text()
22 temp_url = chapter.get('href')
23 chapter_dict[temp_name] = temp_url
24 return chapter_dict
25
26
27# 根据章节的url获取具体的章节内容
28def get_txt(url):
29 html = get_html(url)
30 soup = BeautifulSoup(html, 'lxml')
31 content = soup.find('div', attrs={'class': 'noveltext'})
32
33 # 参考:https://www.zhihu.com/question/277948716/answer/396751680
34 # print(content)
35 div = content.find_all('div')
36 for div_item in div:
37 div_item.decompose()
38
39 # 参考:https://www.jianshu.com/p/d9d2c99267fc?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
40 txt = ''
41 for child in content.stripped_strings: # 获取正文内容
42 txt = txt + child + '\n'
43 return txt
44
45
46if __name__ == "__main__":
47 root_dir = r'.\book'
48 url_ = "http://www.jjwxc.net/onebook.php?novelid=4629295"
49 chapters = get_chapters(url_)
50 for chapter_name, chapter_url in chapters.items():
51 if chapter_url is None:
52 print(chapter_name, "url不存在")
53 continue
54 print("正在保存:", chapter_name)
55 f1 = open(r'%s\%s.txt' % (root_dir, chapter_name), 'w', encoding='utf-8') # 以utf-8编码创建文件
56 chapter_content = get_txt(chapter_url)
57 f1.write(str(chapter_content))
58 f1.close()
59 time.sleep(2)
60 print(chapter_name, "保存成功!")
笔记
requests
安装
11pip install requests
通过Get
请求访问页面(无参数)
41import requests
2r = requests.get('https://www.douban.com/') # 豆瓣首页
3r.text # 网页内容
4r.status_code # 访问网页状态码(200为获取成功,404为找不到页面)
通过Get
请求访问页面(无参数)
41import requests
2r = requests.get('https://www.douban.com/') # 豆瓣首页
3r.text # 网页内容
4r.status_code # 访问网页状态码(200为获取成功,404为找不到页面)
其余内容暂不记录,等以后用到再记录
beautifulSoup
安装
21pip install beautifulSoup4
2pip install lxml # 解析html的第三方解析器
解析html内容 结合requests获取的html内容
51import requests
2from bs4 import BeautifulSoup
3r = requests.get('https://www.douban.com/') # 豆瓣首页
4html = r.text # 获取网页内容
5soup = BeautifulSoup(html, 'lxml') # 解析网页内容
搜索文档树 html文档术语为:文档树。要在文档树中找到所需内容,则需要搜索文档树
81# 参考:https://beautifulsoup.readthedocs.io/zh_CN/latest/#find
2# 基于第2部分基础用法代码
3# find_all() 返回文档中符合条件的所有内容
4div_lists_1 = soup.find_all('div') # 找到文档树中的所有div标签
5div_lists_2 = soup.find_all('div', attrs={'name': 'title'}) # 找到文档树中的所有name属性为title的div标签
6# find() 返回文档树中符合条件的第一个内容
7div_item_1 = soup.find('div') # 找到文档树中的第一个div
8div_item_2 = soup.find('div', attrs={'name': 'title'}) # 找到文档树中的第一个name属性为title的div标签
标签操作 根据搜索文档树的函数,可以找到所需内容对应的标签,但并不是真正所需的内容,因此需要根据标签获取所需内容
81# 参考:https://beautifulsoup.readthedocs.io/zh_CN/latest/#get-text
2# 基于第3部分代码
3# 只获取标签中文本内容get_text()。
4div_text_1 = div_item_1.get_text()
5# 删除文本内容中多余的空行和空格,返回格式为数组
6div_text_list = div_item_1.stripped_strings()
7# 获取标签的指定属性内容
8div_name = div_item_1.get('name')
删除子标签 标签内容存在无用的子标签,可以进行删除
61# 参考:https://www.zhihu.com/question/277948716/answer/396751680
2# 基于第3部分代码
3# 获取name属性为dog的div标签
4div_dog = div_lists_1.find_all('div', attrs={'name': 'dog'})
5for div_item in div_dog: # 删除掉div_lists_1中所有name属性为dog的div标签
6 div_item.decompose()
创建文本文档
在本地创建文本文档
61# 有汉字,因此需要以utf-8编码创建文件
2f1 = open(path, 'w', encoding='utf-8')
3# 将内容写入文本文档,需要转换为str格式
4f1.write(str(content))
5# 关闭文件
6f1.close()
其余内容暂不记录,等以后用到再记录
参考文献
- https://www.jb51.net/article/167314.htm
- https://www.liaoxuefeng.com/wiki/1016959663602400/1183249464292448
- https://beautifulsoup.readthedocs.io/zh_CN/latest/
- https://beautifulsoup.readthedocs.io/zh_CN/latest/#find
- https://www.zhihu.com/question/277948716/answer/396751680
- https://www.jianshu.com/p/d9d2c99267fc