爬虫小说下载

爬虫即按照一定规则,自动的抓取万维网信息的程序或脚本。



URL

爬虫是根据网页的地址来寻找网页的,也就是URL(统一资源定位符)
其一般格式为:

protocol :// hostname[:port] / path / [;parameters][?query]#fragment

# protocol:就是指协议,如百度使用 https协议;

# hostname[:port]:指主机名(还有端口号为可选参数),一般网站默认端口号为80
# 如百度的主机名就是 www.baidu.com,这个就是服务器的地址;

# path:主机资源的具体地址,如目录和文件名等。

requsets库和简单方法

request库是一个非常强大的库,官方中文教程地址:http://docs.python-requests.org/zh_CN/latest/user/quickstart.html

其中的方法和说明

方法 说明
requests.request() 构造一个请求,支撑一下各方法的基础方法
requests.get() 获取HTML网页的主要方法,对应于HTTP的GET
requests.head() 获取HTML网页头信息的方法,对应于HTTP的HEAD
requests.post() 向HTML网页提交POST请求的方法,对应于HTTP的POST
requests.put() 向HTML网页提交PUT请求的方法,对应于HTTP的PUT
requests.patch() 向HTML网页提交局部修改请求,对应于HTTP的PATCH
requests.delete() 向HTML网页提交删除请求,对应于HTTP的DELETE

小说下载

介绍:笔趣看是盗版小说网站,可免费在线阅读,但不支持小说打包下载
目标:爬取笔趣小说网站的小说,打包下载下来
笔趣看:http://www.biqukan.com/

以小说《斗罗大陆》为例:首先打开第一章:
第一章的URL:http://www.biqukan.com/3_3026/1343657.html

用前面提到的requests库获取该页面的HTML信息:

if __name__ = "__main__":
    target = 'http://www.biqukan.com/3_3026/1343657.html'
    req = requests.get(url=target)
    print(req.text)

这样就获取到了页面所有的HTML信息,但其中很多内容我们并不需要,多了很多的div等的HTML标签,这些都是我们不需要的无用信息,我们只需要将其中的正文内容提取出来即可。
所以在获取到了HTML信息后,要将其进行解析,提取所需要的信息。

提取的方法很多,这里用最简单的BeautifulSoup进行解析;

Chrome浏览器在页面内点击右键,选择检查,即可查看页面的HTML内容。

仔细看其中的内容,会发现正文所有的内容都在一个名为:

< d i v i d =" c o n t e n t " c l a s s =" s h o w t x t ">
标签内

观察其他标签,发现class属性为showtxt的div标签只有这一个,于是,利用BeautifulSoup提取其中的内容,代码如下:

from bs4 import BeautifulSoup
import requests

if __name__ = "__main__":
    target = 'http://www.biqukan.com/3_3026/1343657.html'
    req = requests.get(url=target)
    html = req.text
    bf = BeautifluSoup(html,"lxml")
    texts = bf.find_all("div",class_ = "showtxt")
    print(texts)

解析HTML之前,需要创建一个BeautifulSoup对象,BeautifulSoup函数内的参数就是此前已经获取到的html信息。然后使用find_all方法,第一个参数是获取的标签名,第二个参数class _ 是标签的属性。

但我们还是发现多了其他的一些标签不是我们想要的。find_all匹配的返回的结果是一个列表。所以可以提取匹配结果后,使用text属性,提取文本内容,滤除br标签。随后使用replace方法,剔除其中的空格,替换为回车进行分段。 \xa0在html中是用来表示空格的。replace(‘\xa0’*8,’\n\n’)就是去掉下图的八个空格符号,并用回车代替:

这样,第一章就已经下载完成了。
但如果想要下载整本书呢?同样,回到小说的目录页面下,点检查,查看页面的html信息;

可以看到,文章的章节名都存放在class属性为listmain的标签内:

< d i v c l a s s =" l i s t m a i n ">

其中,< div >为父标签,< dl >为子标签,< dd >为孙标签;分别对应开头结尾为< div > < /div >类似形式。
而在< dd > 和< /dd >中找到的目录内容可以看到,存储形式为:

< a href=”/3_3026/1344261.html” >第二百三十六章 大结局,最后一个条件(全书完)

从中可以看到,不同章节的【href】属性不同,而且该属性正好对应着每一章节的URL后半部分,如此一来,我们便可以根据href属性来获取每个章节的连接和名称。

所以,再使用find_all的方法,来首先将目录提取出来:

import requests
from bs4 import BeautifulSoup

if __name__ == "__main__":
    target = "http://www.biqukan.com/3_3026/"    #小说的页面网址
    req = requests.get(url=target)
    html = req.text
    div_bf = BeautifulSoup(html,"lxml")
    div = div_bf.find_all('div',class_ = 'listmain')
    print(div[0])

得到所有的目录内容:

然后要提取其中的章节链接和章节名:

from bs4 import BeautifulSoup

if __name__ == "__main__":
    server = "http://www.biqukan.com"
    target = "http://www.biqukan.com/3_3026/"    #小说的页面网址
    req = requests.get(url=target)
    html = req.text
    div_bf = BeautifulSoup(html,"lxml")
    div = div_bf.find_all('div',class_ = 'listmain')
    a_bf = BeautifulSoup(str(div))
    a = a_bf.find_all('a')
    for each in a:
        print(each.string,server + each.get('href'))

如此便得到了我们想要得到的章节名+链接

于是,将上面的步骤整合一下:
- 首先要定义一个类,其中有属性章节名、章节链接、章节数,网站URL,小说URL等信息
- 然后定义方法:
- 获取下载链接:先通过爬取目标小说的页面获取所有章节名和连接,存入定义的空数组内
- 获取章节内容:得到连接后,返回其中正文内容
- 将文章内容写入文件:以写的方式打开文件,”a”追加模式,tf-8编码格式;先写入章节名,回车;在写入正文;最后再空两行和下一章节隔开。

程序源码

# Author WdZh

# -*- coding:UTF-8 -*-

from bs4 import BeautifulSoup
import requests
import sys

class Download(object):
    '''
    类说明:下载笔趣看网站小说《斗罗大陆》
    '''
    def __init__(self):
        self.server = 'http://www.biqukan.com'
        self.target = "http://www.biqukan.com/3_3026/"
        self.names = []      #存放章节名
        self.urls = []     #存放章节连接
        self.nums = 0        #章节数

    def get_download_url(self):
        '''
        函数说明:获取下载链接
        :return:
        '''
        req = requests.get(url=self.target)
        html = req.text
        div_bf = BeautifulSoup(html,"lxml")
        div = div_bf.find_all("div",class_ = "listmain")
        a_bf = BeautifulSoup(str(div[0]),'lxml')
        a = a_bf.find_all("a")
        self.nums = len(a[15:])         #剔除开头的最新章节以及外传,从第15行开始
        for each in a[15:]:
            self.names.append(each.string)
            self.urls.append(self.server + each.get("href"))

    def get_contents(self,target):
        '''
        获取章节内容
        :param self:
        :param target:
        :return:
        '''
        req = requests.get(url = target)
        html = req.text
        bf = BeautifulSoup(html,"lxml")
        texts = bf.find_all('div',class_ = 'showtxt')
        texts = texts[0].text.replace("\xa0"*8,"\n\n")
        return texts

    def writer(self,name,path,text):
        '''
        将爬取的文章内容写入文件
        :param self:
        :param name:章节名
        :param path:当前路径下,小说保存名称(string)
        :param text:章节内容
        :return:None
        '''
        writer_flag = True
        with open(path,"a",encoding="utf-8") as f:
            f.write(name + '\n')
            f.write(text)
            f.write('\n\n')

if __name__ == "__main__":
    dl = Download()
    dl.get_download_url()
    print("《斗罗大陆》开始下载:")
    for i in range(dl.nums):
        dl.writer(dl.names[i],'斗罗大陆.txt',dl.get_contents(dl.urls[i]))
        sys.stdout.write("已下载:%.3f%%" % float(i/dl.nums) + '\r')
        sys.stdout.flush()          # %.3f是指小数点后三位
    print("《斗罗大陆》下载完成")

猜你喜欢

转载自blog.csdn.net/weixin_42026630/article/details/80723296