Python爬取奇书网(用Python下载小说到本地)

今天我们来进行Python爬取小说网的案例,与前面学习的爬取图片和爬取电影网不同,小说网的数据量比较大,相比前两者要复杂的多。

首先分析需求,我们要对每个分类的小说进行爬取,并且进行分类,不仅是文字还有图片信息,着重考虑的是网页目录,页数跳转和下载后乱码的问题。
Python爬取奇书网(用Python下载小说到本地)_第1张图片
Python爬取奇书网(用Python下载小说到本地)_第2张图片

下面开始写代码吧!

首先导入今天的几个包

import requests
from lxml import etree
from urllib.request import urlretrieve
from urllib.parse import quote
import os
# 正则表达式:从目标字符串提取需要的字符的一种匹配规则。
import re

一部小说的全部信息需要如下代码

# 小说名称
novel_name = div.xpath('h1/text()')[0]
# 小说点击次数
novel_click_num = div.xpath('ul/li[1]/text()')[0].split(":")[-1]
# 小说文件大小
novel_size = div.xpath('ul/li[2]/text()')[0].split(":")[-1]
# 小说书籍类型
novel_file_type = div.xpath('ul/li[3]/text()')[0].split(":")[-1]
# 小说更新日期
novel_update_time = div.xpath('ul/li[4]/text()')[0].split(":")[-1]
# 小说连载状态
novel_status = div.xpath('ul/li[5]/text()')[0].split(":")[-1]
# 小说作者
novel_author = div.xpath('ul/li[6]/text()')[0].split(":")[-1]
# 小说运行环境
novel_run_envir = div.xpath('ul/li[7]/text()')[0].split(":")[-1]
# 小说最新章节
novel_last_chapter = div.xpath('ul/li[8]/a/text()')[0]
# 小说图片的地址
novel_img_url = "https://www.qisuu.la" + html_obj.xpath('//div[@class="detail_pic"]/img/@src')[0]
# 小说的下载地址
# 根据正则表达式提取
pattern_obj = re.compile(r"get_down_url.*?,'(.*?)',", re.S)
novel_download_url = re.search(pattern_obj, response.text).group(1)

全部代码:

import requests
from lxml import etree
from urllib.request import urlretrieve
from urllib.parse import quote
import os
# 正则表达式:从目标字符串提取需要的字符的一种匹配规则。
import re

# 判断是否有奇书网这个文件夹,如果没有,就创建一个并且切换进去
# 如果有则直接切换进去
if not os.path.exists("奇书网"):
    os.mkdir("奇书网")
    os.chdir("奇书网")
else:
    os.chdir("奇书网")
# 首先对网站首页发起请求,目的是为了解析出来每个小说分类的名称和地址
response = requests.get("https://www.qisuu.la/")
html_obj = etree.HTML(response.text)
a_list = html_obj.xpath('//div[@class="nav"]/a')
# 删除首页所在的a标签
del a_list[0]
for a in a_list:
    href = a.xpath("@href")[0]
    text = a.xpath("text()")[0]
    print("正在爬取-{}-分类小说".format(text))
    # 通过分类的名称创建文件夹,保证对应的分类小说存储到对应的文件夹中
    if not os.path.exists(text):
        os.mkdir(text)
        os.chdir(text)
    else:
        os.chdir(text)
    # 根据每个分类的href属性值,拼接出来每个分类详细的地址
    type_url = "https://www.qisuu.la" + href
    # 对每个小说分类的地址发起访问
    response = requests.get(type_url)
    # 编写正则表达式规则,从每个小说分类首页提取该小说分类的总页数
    # .*?:非贪婪匹配
    pattern_obj = re.compile(r"页次:1/(.*?) 每页", re.S)
    # 根据正则表达式匹配规则,从页面源代码中提取总页数
    total_num = re.search(pattern_obj, response.text).group(1)
    # 正则表达式匹配到的total_num是一个字符串,所有需要用int转换一下
    for page_num in range(1, int(total_num) + 1):
        print("正在爬取第{}页小说".format(page_num))
        if not os.path.exists("第{}页".format(page_num)):
            os.mkdir("第{}页".format(page_num))
            os.chdir("第{}页".format(page_num))
        else:
            os.chdir("第{}页".format(page_num))
        # 在小说分类地址的基础上,拼接出来每一页小说的地址
        every_page_url = type_url + "index_{}.html".format(page_num)
        # 对每一页小说发起访问
        response = requests.get(every_page_url)
        html_obj = etree.HTML(response.text)
        # 解析出来每一本小说的地址
        a_list = html_obj.xpath('//div[@class="listBox"]/ul/li/a')
        for a in a_list:
            href = a.xpath("@href")[0]
            text = a.xpath("text()")[0]
            print("正在爬取-{}-小说".format(text))
            if not os.path.exists(text):
                os.mkdir(text)
                os.chdir(text)
            else:
                os.chdir(text)
            # 拼接出来每一本小说的地址,然后发起访问
            every_novel_url = "https://www.qisuu.la" + href
            response = requests.get(every_novel_url)
            response.encoding = "utf-8"
            html_obj = etree.HTML(response.text)
            div = html_obj.xpath('//div[@class="detail_right"]')[0]
            # 小说名称
            novel_name = div.xpath('h1/text()')[0]
            # 小说点击次数
            novel_click_num = div.xpath('ul/li[1]/text()')[0].split(":")[-1]
            # 小说文件大小
            novel_size = div.xpath('ul/li[2]/text()')[0].split(":")[-1]
            # 小说书籍类型
            novel_file_type = div.xpath('ul/li[3]/text()')[0].split(":")[-1]
            # 小说更新日期
            novel_update_time = div.xpath('ul/li[4]/text()')[0].split(":")[-1]
            # 小说连载状态
            novel_status = div.xpath('ul/li[5]/text()')[0].split(":")[-1]
            # 小说作者
            novel_author = div.xpath('ul/li[6]/text()')[0].split(":")[-1]
            # 小说运行环境
            novel_run_envir = div.xpath('ul/li[7]/text()')[0].split(":")[-1]
            # 小说最新章节
            novel_last_chapter = div.xpath('ul/li[8]/a/text()')[0]
            # 小说图片的地址
            novel_img_url = "https://www.qisuu.la" + html_obj.xpath('//div[@class="detail_pic"]/img/@src')[0]
            # 小说的下载地址
            # 根据正则表达式提取
            pattern_obj = re.compile(r"get_down_url.*?,'(.*?)',", re.S)
            novel_download_url = re.search(pattern_obj, response.text).group(1)
            print("没有转换之前的小说地址:", novel_download_url)
            # 从小说下载地址中把其中的文字部分取出来,使用quote对文字部分内容进行编码
            novel_download_url = novel_download_url.replace(novel_download_url.split("/")[-1].split(".")[0],
                                                            quote(novel_download_url.split("/")[-1].split(".")[0]))
            print("转换过后的下载地址是:", novel_download_url)
            # 下载小说图片
            urlretrieve(novel_img_url, "{}.jpg".format(novel_name))
            # 由于使用urlretrieve进行文件下载的时候,下载地址中不能含有中文,需要进行对中文进行转换
            urlretrieve(novel_download_url, "{}.txt".format(novel_name))
            f = open("{}信息.txt".format(novel_name), "w", encoding="utf-8")
            # write():文件写入
            f.write("小说名称:{}".format(novel_name))
            f.write("\n")
            f.write("点击次数:{}".format(novel_click_num))
            f.write("\n")
            f.write("文件大小:{}".format(novel_size))
            f.write("\n")
            f.write("书籍类型:{}".format(novel_file_type))
            f.write("\n")
            f.write("更新日期:{}".format(novel_update_time))
            f.write("\n")
            f.write("连载状态:{}".format(novel_status))
            f.write("\n")
            f.write("小说作者:{}".format(novel_author))
            f.write("\n")
            f.write("运行环境:{}".format(novel_run_envir))
            f.write("\n")
            f.write("最新章节:{}".format(novel_last_chapter))
            f.write("\n")
            f.write("图片地址:{}".format(novel_img_url))
            f.write("\n")
            f.write("下载地址:{}".format(novel_download_url))
            f.write("\n")
            print("文件关闭")
            # 关闭文件
            f.close()
            os.chdir(os.pardir)
        os.chdir(os.pardir)
    os.chdir(os.pardir)

运行程序后,
Python爬取奇书网(用Python下载小说到本地)_第3张图片

我这里网路比较卡,只下载了一本就停止运行了 ,如果想下载全部,耐心等待就好了,489页 每页25本,太多了。哈哈 运行完后去你程序的源文件就可以看到奇书网文件夹了,好看的小说就都在里面啦!
Python爬取奇书网(用Python下载小说到本地)_第4张图片

做的不好 仅供参考

你可能感兴趣的:(Python基础,解析网页)