流浪的二胡 发表于 2018-10-23 18:03

【学习笔记】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

流浪的二胡 发表于 2018-10-23 18:08

这个程序的容错率是很不好的,中间一次网络请求未响应,程序就会中断,再次运行的话还是冲第一章开始爬取,txt内的文本就会重复显示,还需要手动清空一下。

后面要完善的就是错误机制了,用try   except语句,结合错误信息,当出错后可以采取某种自己定义的措施,而不是中断程序。

一开始要是定义函数来完成功能的话,程序会更好,。。。。。。先放下次了。

流浪的二胡 发表于 2018-10-23 20:08

liphily 发表于 2018-10-23 19:45
神奇的python啊。我还是喜欢matlab和c——
不是不想学新东西,而是觉得python的写法和库,不太规范。看的 ...

Python的语言很接近自然语言,读、写很自然,很好懂。也因此导致程序中不规范的地方很多,这是弊端。
c、matlab就很计算机语言了,需要专门学习后方可适应。

黄家驹丶 发表于 2018-10-23 18:05

学习一下。

我下了 发表于 2018-10-23 18:26

付费文章也可以爬取么。。

Pear 发表于 2018-10-23 18:48

学习啦{:1_919:}谢

shaokui123 发表于 2018-10-23 19:02

感谢分享学习经验

FENGMUTIAN 发表于 2018-10-23 19:16

作为老书虫,必须要学啊,嘿嘿

dreamweaver0314 发表于 2018-10-23 19:26

谢谢楼主的热心教学~学习一下!

teondy 发表于 2018-10-23 22:30

感谢分享谢谢学到了
页: [1] 2
查看完整版本: 【学习笔记】Python爬取某一本小说