【学习笔记】Python爬取某一本小说
本帖最后由 流浪的二胡 于 2018-10-23 20:19 编辑最近刀剑神域第三季真的不错,无奈动画一周才更新一次,索性就想先把原著小说看了解解馋。
于是就找到了这个小说网站:http://www.wuyanxia.net/read/77374.html,本来是想简简单单的把它按
TXT格式下载一下的,谁知心中的Python爬虫之火燃料了起来,索性就直接开整,下面是步骤、详情----------
需要用到的库:1:requests第三方插件库,需要安装,作用是对网页发起请求,获取网页内容。
2:BeautifulSoup第三方插件库,需要安装bs4,作用是对html网页进行遍历,以树状结构显示各个节点。
库内有许多种方法,可以达到许多目的。详情请看,BeautifulSoup4中文文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html
3:lxml解析库,也需要单独下载,和beautifulsoup搭配使用。
PS:用到的方法都是在网上看到的比较新的方法了,语法也是Python3的语法,得益于第三方插件库的强大功能,爬取写的很舒服
一、明确要爬取内容所在的位置。(这里先说怎样获取各章节的网址)
每一卷的标题,每一章节的网址都可以看到,而我们要的就是这个网址。思路:通过爬取获得每一章节小说
的网址,对每一个章节进行遍历读取,最后将文本内容存放到本地。
从headers中我们可以看到网站内容是以html格式存储,字符编码是GBK。当然还可以看到user-agent的内容,
借助它可以模拟浏览器访问。
ps:为了在显示出现乱码时能够知道,文本当前字符编码是什么,是在用什么编码对其进行解读,so,这里标注一下
字符集编码的转化过程。*******beautifulsoup以 UTF-8 格式获取数据将其转换为Unicode*********
GBK-----》UTF-8-------》Unicode
url='http://www.wuyanxia.net/read/77374.html'
headers={
"user-agent":'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/69.0.3497.81 Safari/537.36'
}
request_url=requests.get(url,headers=headers) #发起请求
det_contents=request_url.text #获取网页内容
html_soup=BeautifulSoup(det_contents,'lxml') #建立BeautifulSoup对象,树形显示html内容
html_title=html_soup.title.string #显示title的内容
html_list=html_soup.body.find_all('a') #beautifulsoup自行遍历显示html中所有<a /a>内容
这一段会将所有<a href="/read/77374/8826758.html">一卷全</a>都遍历出来
<a href="/read/77374/---------.html">name</a>
<a href="/read/77374/---------.html"> </a>
<a href="/read/77374/---------.html"> </a>
.......................
而我们要的只是#/read/77374/8826758.html#这一部分,多看几个网址会发现,每个章节的网址只是最
后面的7位数不同,前面的均相同。
就像这样http://www.wuyanxia.net/read/77374/xxxxxxx.html
for list in html_list: #遍历所有<a>中的内容并将其放在list中
list_number=list.get('href') #遍历获取每一章小说的网址,最终存在list_number中
if 23<len(list_number)<30: #筛选符合目标要求的网址
list_ok=
在遍历过程中发现掺杂一些其它网址,通过对比发现他们和目标网址在长度上差异很大,目标网址长度24、25而其它网址
为23以下,30以上,所以用一个if语句就轻松过滤掉了杂项。现在我们已经将所有需要的/read/77374/xxxxxxx.html放在了list_ok中
接下来对每一个网址都加上http://www.wuyanxia.net这一部分,遍历的访问即可。
for list_ok1 in list_ok: #遍历list_ok将其放在list_ok1中,对每一个网址放松请求,获取内容,最终写入
count=count+1
url3='http://www.wuyanxia.net'+ list_ok1
get_url3=requests.get(url3,headers=headers)
get_url3_1=get_url3.text
get_url3_soup=BeautifulSoup(get_url3_1,'lxml')
list_final_title=get_url3_soup.find('span', id="htmltimu") #获取小说章节标题
list_final_content=get_url3_soup.find('div',id="htmlContent") #获取小说章节内容
list_final_title_1=list_final_title.get_text()
list_final_content_1=list_final_content.get_text()
list_final_content_2=list_final_content_1
这一部分建议各位自己结合beautifulsoup文档和上面获取href的思路来分析一下。
下面就需要将获取到的小说每一章的文本内容存放到本地了。
with open('swort_Alice.txt','a') as file_object:
file_object.write(list_final_title_1.replace(u'\xa0', u'').
replace(u'\xa9',u'').replace(u'\ufffd',u''))
file_object.write(list_final_content_2.replace(u'\xa0', u'').
replace(u'\xa9',u'').replace(u'\ufffd',u''))
在这里写入的时候我就被转换来转换去的字符集编码给坑到了,windows控制台默认以GBK格式来写入
然而,网页源代码中的的utf-8 编码是:\xc2 \xa0,通过后,转换为Unicode字符为:\xa0,
当显示到DOS窗口上的时候,转换为GBK编码的字符串,但是\xa0这个Unicode字符没有对应的
GBK 编码的字符串,所以出现错误。\xa9这个错误类似。
另外一个方法:在写入时用encoding('utf-8')设置编码格式,这样也可以避免问题。
完整代码:
from bs4 import BeautifulSoup
import requests
url='http://www.wuyanxia.net/read/77374.html'
headers={
"user-agent":'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/69.0.3497.81 Safari/537.36'
}
request_url=requests.get(url,headers=headers) #发起请求
det_contents=request_url.text #获取网页内容
html_soup=BeautifulSoup(det_contents,'lxml') #建立BeautifulSoup对象,树形显示html内容
html_title=html_soup.title.string #显示title的内容
html_list=html_soup.body.find_all('a') #遍历显示html中所有<a /a>节点内容
count=0
list_ok=[] #定义一个列表,后面将获取的网址放在其中
for list in html_list: #遍历所有<a>中的内容并将其放在list中
list_number=list.get('href') #遍历获取每一章小说的网址,最终存在list_number中
if 23<len(list_number)<30: #筛选符合目标要求的网址
list_ok= #符合要求的网址赋值给list_ok,每一个网址都是列表中的一个元素,一个网址是一个整体。这样后面就可以准确访问网址。
for list_ok1 in list_ok: #遍历list_ok将其放在list_ok1中,对每一个网址放松请求,获取内容,最终写入
#本地txt中
count=count+1
url3='http://www.wuyanxia.net'+ list_ok1
get_url3=requests.get(url3,headers=headers)
get_url3_1=get_url3.text
get_url3_soup=BeautifulSoup(get_url3_1,'lxml')
list_final_title=get_url3_soup.find('span', id="htmltimu") #获取小说章节标题
list_final_content=get_url3_soup.find('div',id="htmlContent") #获取小说章节内容
list_final_title_1=list_final_title.get_text()
list_final_content_1=list_final_content.get_text()
list_final_content_2=list_final_content_1
with open('swort_Alice.txt','a') as file_object:
file_object.write(list_final_title_1.replace(u'\xa0', u'').
replace(u'\xa9',u'').replace(u'\ufffd',u''))
file_object.write(list_final_content_2.replace(u'\xa0', u'').
replace(u'\xa9',u'').replace(u'\ufffd',u''))
参考过的资料:
http://stackoverflow.com/questions/10993612/python-removing-xa0-from-string
https://www.cnblogs.com/cwp-bg/p/7835434.html
https://blog.csdn.net/jim7424994/article/details/22675759
---------------------------------------------------------------------------------------------------------------------------
写在结尾,当我将小说爬取出来后发现,我竟然不想看了enmmmmm,心思淡了。。。。。。
爬取的刀剑神域小说我放在百度云了,网址放下面:
链接:https://pan.baidu.com/s/1JU46T-sW662co-WE2Y0d9w
提取码:u6wx
这个程序的容错率是很不好的,中间一次网络请求未响应,程序就会中断,再次运行的话还是冲第一章开始爬取,txt内的文本就会重复显示,还需要手动清空一下。
后面要完善的就是错误机制了,用try except语句,结合错误信息,当出错后可以采取某种自己定义的措施,而不是中断程序。
一开始要是定义函数来完成功能的话,程序会更好,。。。。。。先放下次了。 liphily 发表于 2018-10-23 19:45
神奇的python啊。我还是喜欢matlab和c——
不是不想学新东西,而是觉得python的写法和库,不太规范。看的 ...
Python的语言很接近自然语言,读、写很自然,很好懂。也因此导致程序中不规范的地方很多,这是弊端。
c、matlab就很计算机语言了,需要专门学习后方可适应。 学习一下。 付费文章也可以爬取么。。 学习啦{:1_919:}谢 感谢分享学习经验 作为老书虫,必须要学啊,嘿嘿 谢谢楼主的热心教学~学习一下! 感谢分享谢谢学到了
页:
[1]
2