记一次图片爬虫经历

最近由于需要帮朋友找人教版初中地理教材pdf资料,人教出版社官方提供了七年级下册和八年级下册的pdf资源,上册需要自己想办法啦!经过一番信息检索,发现搜狐上居然有提供我想要的版本教材扫描版,果断下载呀!可是在下载过程中遇到了许多问题,下面讲述一下本次资源获取艰辛之路

网页打印pdf

​ 搜狐提供教材图片版,第一想法当然是将网页打印成pdf,可是网页上还有许多杂七杂八的东西是我不需要的,不过这可难不倒我,在浏览器审查元素的支持下,我将不需要的内容全部删除啦,并且,简单加几条css规则,这样就可以打印成pdf了呗,事实证明这是可行的,但是有一点小小的瑕疵,新的pdf一页内容和原来的教材一页内容对不上,意味着原来的一页可能在这里就被分成上下两截。作为强迫症患者的我当然不能忍受这个,于是开始了进阶尝试。

保存网页

​ 想法很简单,将整个网页保存下来,这样不就所有的图片都下载好了吗!说干就干,直接一个Ctrl+S,我看到了一个放满了图片的文件夹,每一张图片就是一页教材,真是太完美了。No!一点儿也不美丽,每一张图片都是一串乱七八糟的字符命名,根本没有顺序可言,那我怎么将这堆图片合并成一个pdf呢,难道要我每张图片根据页面重命名一下?不不不,这种活儿我可不会干!

python爬虫

​ 既然半自动保存图片失败了,那就上全自动保存图片。对于一个坚决不做机械式重复劳动的不折腾会死星人,让我每张图片重命名一次,和直接在网页上一张一张图片下载有什么区别呢?可别忘了自己还有技能树呢!对于这种任务,直接上python,两个包requests+lxml是我的最爱,打开我的vscode,两下半就完成一个爬虫,运行一下,所有的教材图片有序躺在我的文件夹中,完全不用自己重命名排个序什么的。

合成pdf

​ 最后说一下如何将这堆图片打包成一个pdf,有同学可能想到了新建一个空白word,然后插入所有图片,最后导出pdf。不得不承认,这是可行的方法,但不是最优的方法。条条大路通罗马,当然要选择一条平坦的捷径咯,打开福昕高级版PDF编辑器,创建,合并文件,然后选择图片的整个文件夹,点击合并即可!

附录

import time
import logging
from pathlib import Path
from lxml import etree
import requests

def create_logger(loggername:str='logger', levelname:str='DEBUG', console_levelname='INFO'):
    levels = {
        'DEBUG': logging.DEBUG,
        'INFO': logging.INFO,
        'WARNING': logging.WARNING,
        'ERROR': logging.ERROR,
        'CRITICAL': logging.CRITICAL
    }

    logger = logging.getLogger(loggername)
    logger.setLevel(levels[levelname])

    logger_format = logging.Formatter("[%(asctime)s][%(levelname)s][%(filename)s][%(funcName)s][%(lineno)03s]: %(message)s")
    console_format = logging.Formatter("[%(levelname)s] %(message)s")

    handler_console = logging.StreamHandler()
    handler_console.setFormatter(console_format)
    handler_console.setLevel(levels[console_levelname])

    # path = Path(__file__).parent/'logs' # 日志目录
    path = Path('./logs')
    path.mkdir(parents=True, exist_ok=True)
    today = time.strftime("%Y-%m-%d")     # 日志文件名
    common_filename = path / f'{today}.log'
    handler_common = logging.FileHandler(common_filename , mode='a+', encoding='utf-8')
    handler_common.setLevel(levels[levelname])
    handler_common.setFormatter(logger_format)

    logger.addHandler(handler_console)
    logger.addHandler(handler_common)

    return logger

logger = create_logger('Crawler')

class Crawler:
    def __init__(self, url, path):
        self.url = url
        self.path = Path(path)
        self.path.mkdir(parents=True, exist_ok=True) # 安全创建目录
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362"
        }


    def _download(self, url, filename):
        try:
            resp = requests.get(url)
        except:
            logger.debug(f'请求异常')

        if 200 != resp.status_code:
            logger.debug(f'请求失败')

        with filename.open('wb') as fp:
            fp.write(resp.content)

        logger.info(f'完成下载{filename} {url}')

    def cycle(self):
        try:
            resp = requests.get(self.url, headers=self.headers)
        except:
            logger.debug(f'请求异常')
        if 200 != resp.status_code:
            logger.debug(f'请求失败')
        try:
            html = etree.HTML(resp.text)
        except:
            logger.debug(f'转换异常')
        imgs = html.xpath('//article[@id="mp-editor"]/p/img/@src')
        for (idx, img) in enumerate(imgs):            
            filename = self.path/f'{idx:03}.jpg'
            logger.info(f'准备下载{filename} {img}')
            self._download(img, filename)

if __name__ == "__main__":
    # url = "https://www.sohu.com/a/240462346_796524" # 人教版地理教材八年级上册
    # url = "https://www.sohu.com/a/240462516_796524" # 人教版地理教材七年级上册
    # path = './images'
    logger.info(f'欢迎使用搜狐图片下载器')
    logger.info(f'如:人教版地理教材八年级上册 "https://www.sohu.com/a/240462346_796524"')
    url = input(f'请输入目标网址: ')
    path = input(f'请输入保存路径: ')
    crawler = Crawler(url, path)

    crawler.cycle()

你可能感兴趣的:(记一次图片爬虫经历)