基于Scrapy的交互式漫画爬虫

基于Scrapy的交互式漫画爬虫

基于Scrapy的交互式漫画爬虫

前言

该项目始于个人兴趣,本意为给无代码经验的朋友做到能开箱即用
阅读此文需要少量Scrapy,PyQt 知识,全文仅分享交流 摘要思路,如需可阅读源码,欢迎提 issue

一、Scrapy 思路构想

基类封装了框架所需方法,框架基于三级页面 (标题-章节-详情页) 网站,内部方法分岔线基于交互思想

GUI传参并开启后台 >> spider开始工作于重写的start_requests >> 在parse等处理resp的方法后挂起等待选择

执行顺序为 (1) parse -- frame_book --> (2) parse_section -- frame_section -->(3) yield item

pipeline对item作最后的下载,改名等处理,至此spider完成一个生命周期,发送结束信号逻辑交回GUI

BaseClassSpider class BaseComicSpider(scrapy.Spider): """改写start_requests""" step = 'loop' current_status = {} print_Q = None current_Q = None step_Q = None bar = None # 此处及以上变量均为交互信号 total = 0 # item 计数,pipeline处讲解 search_url_head = NotImplementedError('需要自定义搜索网址') mappings = {'': ''} # mappings自定义关键字对应网址 # …………………… def parse(self, response): frame_book_results = self.frame_book(response) yield scrapy.Request(url=title_url, ………………) def frame_book(self, response) -> dict: raise NotImplementedError def elect_res(self, elect: list, frame_results: dict, **kw) -> list: # 封装方法实现(1)选择elect与(2)frame方法格式化后的显示result -> # -> 返回[[elected_title1, title1_url], [title2, title2_url]……]的格式数据 pass # …………………… def close(self, reason): # ………处理管道,session等关闭工作 self.print_Q.put('结束信号') InstanceClassSpider

后台执行的实例,简单的二级页面仅需复写两个frame方法,对应的是扩展的基类2

frame方法功能为定位目标元素位置,实时清洗数据返回给前端显示

class ComicxxxSpider(BaseComicSpider2): name = 'comicxxx' allowed_domains = ['m.xxx.com'] search_url_head = 'http://m.xxx.com/search/?keywords=' mappings = {'更新': 'http://m.xxx.com/update/', '排名': 'http://m.xxx.com/rank/'} def frame_book(self, response): # …………………… title = target.xpath(title_xpath).get().strip() self.print_Q.put(example_b.format(str(x + 1), title)) # 发送前端print信号 def frame_section(self, response): pass # 类上 setting

setting.py自定义部分与部署相关,使用 的方法读取配置文件构成变量

IMAGES_STORE, log_path, PROXY_CUST, LOG_LEVEL = get_info() os.makedirs(f'{log_path}', exist_ok=True) # 日志输出 LOG_FILE = f"{log_path}/scrapy.log" SPECIAL = ['joyhentai'] pipelines def file_path(self, request, response=None, info=None): """图片下载存储前调用,默认为url的md5后字符串,此处修改成自定义的有序命名""" title = sub(r'([|.:<>?*"\\/])', '-', request.item.get('title')) # 对非法字符预处理 section = sub(r'([|.:<>?*"\\/])', '-', request.item.get('section')) page = '第%s页.jpg' % request.item.get('page') spider = self.spiderinfo.spider # setting.py的参数在此使用 basepath = spider.settings.get('IMAGES_STORE') path = f"{basepath}\\特殊\\{title}" if spider.name in spider.settings.get( 'SPECIAL') else f"{basepath}\\{title}\\{section}\\" os.makedirs(path, exist_ok=True) return os.path.join(path, page) def image_downloaded(self, response, request, info): """继承的ImagesPipeline图片(文件)下载完成方法,下载进度条动态显示的实现就在此处""" self.now += 1 # (ComicPipeline)self.now即为现时处理量 spider = self.spiderinfo.spider percent = int((self.now / spider.total) * 100) # spider.total即为item的总任务量 if percent > self.threshold: percent -= int((percent / self.threshold) * 100) # 进度缓慢化(算法待优化) spider.bar.put(int(percent)) # 后台打印百分比进度扔回GUI界面 super(ComicPipeline, self).image_downloaded(response=response,request=request, info=info)

其他:Items与Middlewares要点不多,略过

二、GUI (Qt) 主界面及功能

主界面

按键逻辑:槽函数实现,内部实现一定量的按钮禁用方法引导操作

选取网站 按钮与 输入关键字 构成参数,由→搜索 按钮触发工作线程等生成,然后替换成 Next 按钮

Next 按钮为正常流程 -- 触发解除后台因等待输入造成的主动阻塞 同时传递 输入序号 的值

Retry 按钮承担后台Spider中parse方法间的逆跳转,以及重启GUI的功能

视窗与信息

主视窗textbrowser,流式显示;整体内联其他视窗,略过

说明按钮通用说明、底下状态栏通过setStatusTip方法于各操作时提供人性化操作提示

进度条,关联 的信号输出

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfsfj.html