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 BeautifulSoup2import time3import requests456# 访问url,返回html页面7def get_html(url):8 r = requests.get(url)9 r.raise_for_status()10 r.encoding = r.apparent_encoding11 return r.text121314# 从列表页获取小说章节名和链接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_url24 return chapter_dict252627# 根据章节的url获取具体的章节内容28def get_txt(url):29 html = get_html(url)30 soup = BeautifulSoup(html, 'lxml')31 content = soup.find('div', attrs={'class': 'noveltext'})3233 # 参考:https://www.zhihu.com/question/277948716/answer/39675168034 # print(content)35 div = content.find_all('div')36 for div_item in div:37 div_item.decompose()3839 # 参考:https://www.jianshu.com/p/d9d2c99267fc?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation40 txt = ''41 for child in content.stripped_strings: # 获取正文内容42 txt = txt + child + '\n'43 return txt444546if __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 continue54 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 requests2r = requests.get('https://www.douban.com/') # 豆瓣首页3r.text # 网页内容 4r.status_code # 访问网页状态码(200为获取成功,404为找不到页面)通过Get请求访问页面(无参数)
41import requests2r = requests.get('https://www.douban.com/') # 豆瓣首页3r.text # 网页内容 4r.status_code # 访问网页状态码(200为获取成功,404为找不到页面)其余内容暂不记录,等以后用到再记录
beautifulSoup
安装
21pip install beautifulSoup42pip install lxml # 解析html的第三方解析器解析html内容 结合requests获取的html内容
51import requests2from bs4 import BeautifulSoup3r = requests.get('https://www.douban.com/') # 豆瓣首页4html = r.text # 获取网页内容5soup = BeautifulSoup(html, 'lxml') # 解析网页内容搜索文档树 html文档术语为:文档树。要在文档树中找到所需内容,则需要搜索文档树
81# 参考:https://beautifulsoup.readthedocs.io/zh_CN/latest/#find2# 基于第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') # 找到文档树中的第一个div8div_item_2 = soup.find('div', attrs={'name': 'title'}) # 找到文档树中的第一个name属性为title的div标签标签操作 根据搜索文档树的函数,可以找到所需内容对应的标签,但并不是真正所需的内容,因此需要根据标签获取所需内容
81# 参考:https://beautifulsoup.readthedocs.io/zh_CN/latest/#get-text2# 基于第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/3967516802# 基于第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
