目录

用python爬取《龙珠·超次元乱战》漫画并转化成pdf阅读

需求描述

为了回忆童年,龙珠的漫画、动漫、剧场版已经基本看完了。突然又发现了有个叫《龙珠·超次元乱战》的同人漫画,看评价还不错,于是去官网上去阅读,谁知这是一个国外运营的网站,是供全球读者观看的,这个小水管的服务器自然看起来也就特别慢了,刷新图片都要几秒才能出来。因此产生了想要下载之后观看的想法,秉着懒人不做批量化事情的思想,决定采用程序进行抓取和下载。

问题分析

源码获取

直接使用requests库进行下载源码即可:

r = requests.get(self.CHAPTER_LIST_URL)
html = r.text
print(u'网页源码获取成功...')

源码查看

<div class="cadrelect chapters " ch='7'><a href='chapters.html?chapter=7'><img src='/cn/pages/small/0144.jpg' alt='[Chapter Cover]' /></a><h4>Chapter 7: 休息一下吃个午饭吧</h4><p><a href='page-144.html' class=''>144</a><a href='page-145.html' class=''>145</a><a href='page-146.html' class=''>146</a><a href='page-147.html' class=''>147</a><a href='page-148.html' class=''>148</a><a href='page-149.html' class=''>149</a><a href='page-150.html' class=''>150</a><a href='page-151.html' class=''>151</a><a href='page-152.html' class=''>152</a><a href='page-153.html' class=''>153</a><a href='page-154.html' class=''>154</a><a href='page-155.html' class=''>155</a><a href='page-156.html' class=''>156</a><a href='page-157.html' class=''>157</a><a href='page-158.html' class=''>158</a><a href='page-159.html' class=''>159</a><a href='page-160.html' class=''>160</a><a href='page-161.html' class=''>161</a><a href='page-162.html' class=''>162</a><a href='page-163.html' class=''>163</a><a href='page-164.html' class=''>164</a><a href='page-165.html' class=''>165</a><a href='page-166.html' class=''>166</a><a href='page-167.html' class=''>167</a></p></div>

代码几乎都是这样的形式,通过表达式抓取即可。

# 使用正则提取数据
        # 提取大块数据的正则
        pattern1 = '<div\sclass="cadrelect\s.+'
        # 提取章节信息的正则
        pattern2 = "ch='(\d+)'><a\shref=\S+\ssrc='(\S+)'\s\S+\s\S+\s\S+<h4>(.+)</h4>"
        # 提取图片的正则
        pattern3 = "href='page-(\d+).html"
        result1 = re.findall(pattern1, html)
        datas = []
        for chatper_text in result1:
            data = {}
            # 解析每一章节
            result2 = re.findall(pattern2, chatper_text)
            data['id'] = result2[0][0]
            data['cover'] = self.get_absolute_url(result2[0][1])
            data['name'] = result2[0][2]
            # 图片
            result3 = re.findall(pattern3, chatper_text)
            # data['images'] = [self.make_image_url(i) for i in result3]
            data['image_indexs'] = result3
            datas.append(data)
        self.datas = datas

经过这样处理之后,得到的数据的格式如下:

[
            {
                id: 章节序号,
                name: 章节名称,
                cover: 封面图片的地址,
                images: [
                    每一个图片的地址
                ]
            }
        ]

图片下载

    def download(self):
        r"""
        下载所有图片。
        在存放数据的文件中,建立以章节名称建立文件夹,并把所有图片下载到对应的文件夹中。
        :return:  无
        """
        for data in self.get_chapters():
            # 建立文件夹
            dir_path = os.path.join(self.get_dir_path(), data['name'])
            if not os.path.exists(dir_path):
                os.makedirs(dir_path)
            # 下载文件
            for i in data['image_indexs']:
                image = self.make_image_url(i, self.suffix)
                if self.image_downloaded_by_index(data['name'], i):
                    print(u'%s已经下载' % i)
                else:
                    # 没有下载
                    image = self.make_image_url(i, self.suffix)
                    try:
                        basename = os.path.basename(image)
                        filepath = os.path.join(dir_path, basename)
                        urlretrieve(image, filepath)
                        print(basename + u'下载成功')
                    except:
                        self.change_suffix()
                        image = self.make_image_url(i, self.suffix)
                        basename = os.path.basename(image)
                        filepath = os.path.join(dir_path, basename)
                        # 最后一次尝试
                        try:
                            urlretrieve(image, filepath)
                            print(basename + u'下载成功')
                        except:
                            # 尝试使用php的方式下载
                            try:
                                self.download_from_php(data['name'], i)
                            except:
                                self.download_fail(i)

                    time.sleep(1)
            # 处理完以章
            print(u'《%s》下载成功' % data['name'])

pdf生成

首先安装reportlab库:

pip install reportlab

然后再github上下载这个库:

https://github.com/wizard1989/Unite-multiple-pictures-into-pdf

接着使用自己写的PdfHandler来执行:

r"""
将下载的图片打包成pdf
"""
import os

from unite_pictures_into_pdf import unite_pictures_into_pdf
from Fetcher import Fetcher

class PdfHandler(object):
    r"""
    打包器
    """
    # 保存pdf的文件夹
    output_name = 'pdfs'
    # 根路径
    BASE_DIR = os.path.dirname(__file__)

    def convert_chapter(self, chapter_name):
        r"""
        转化一章
        :param chapter_name: 章节名称
        :return:  无
        """
        print(u"正在处理《%s》" % chapter_name)
        outputPdfName = chapter_name
        pathToSavePdfTo = os.path.join(self.BASE_DIR, self.output_name)
        if not os.path.exists(pathToSavePdfTo):
            os.makedirs(pathToSavePdfTo)
        pathToPictures = os.path.join(self.BASE_DIR, Fetcher.dir_name, chapter_name)
        print(pathToPictures)
        splitType = "none"
        numberOfEntitiesInOnePdf = 1
        listWithImagesExtensions = ["png", "jpg"]
        picturesAreInRootFolder = True
        nameOfPart = "volume"
        unite_pictures_into_pdf(outputPdfName, pathToSavePdfTo, pathToPictures, splitType, numberOfEntitiesInOnePdf,
                                listWithImagesExtensions, picturesAreInRootFolder, nameOfPart)

    def convert_chapters(self):
        r"""
        转化所有章节
        :return:
        """
        dir_path = os.path.join(self.BASE_DIR, Fetcher.dir_name)
        dirnames =os.listdir(dir_path)
        dirnames = [d for d in dirnames if d != ".DS_Store"]
        for dirname in dirnames:
            self.convert_chapter(dirname)

if __name__ == '__main__':
    PdfHandler().convert_chapters()

注意事项

会遇到图片截断的问题,需要修改一下reportlab
修改reportlab/lib/utils.py,第530行改成下面的东西:

    try:
        from PIL import Image
        from PIL import ImageFile
        ImageFile.LOAD_TRUNCATED_IMAGES = True
    except ImportError:
        try:
            import Image
        except ImportError:
            Image = None

运行

首先运行Fetcher().download(),然后运行PdfHandler().convert_chapters()即可。

结果

用python爬取《龙珠·超次元乱战》漫画并转化成pdf阅读-LMLPHP
所有pdf会上传到csdn上。地址如下:
csdn不让上传大于220MB的文件。。。。
如果有志同道合的人的话,可以在评论区反映。

10-06 17:34