selenium自动化测试+OCR-获取图片页面小说

随着爬虫技术的发展,反爬虫技术也越来越高。

目前有些网站通过自定义字体库的方式实现反爬,主要表现在页面数据显示正常,但是页面获取到的实际数据是别的字符或者是一个编码。
这种反爬需要解析网站自己的字体库,对加密字符使用字体库对应字符替换。需要制作字体和基本字体间映射关系。
还有些网站通过图片加载内容的方式实现反爬,想要获取网页内容,可以结合使用OCR技术获取图片文字内容。

第一步:先获取网页内容截图

结合之前《selenium自动化测试-获取动态页面小说》相关的文章代码,改造下,封装成一个新方法,只获取小说网页内容截图,按章节ID分目录保存每页截图文件。

依旧采用拆分步骤细化功能模块封装方法编写代码,便于后续扩展功能模块,代码中缺少的封装方法代码,详情参考之前的《selenium自动化测试》文章。

def spider_novel_content_save_image(req_dict):'''@方法名称: 爬取小说章节明细内容,保存内容截图文件@中文注释: 爬取小说章节明细内容,保存内容截图文件@入参:@param req_dict dict 请求容器@出参:@返回状态:@return 0 失败或异常@return 1 成功@返回错误码@返回错误信息@param rsp_dict dict 响应容器@作    者: PandaCode辉@weixin公众号: PandaCode辉@创建时间: 2023-09-26@使用范例: spider_novel_content_save_image(req_dict)'''try:if (not type(req_dict) is dict):return [0, "111111", "请求容器参数类型错误,不为字典", [None]]# 章节目录文件名json_name = req_dict['novel_name'] + '.json'# 检查文件是否存在if os.path.isfile(json_name):print('json文件存在,不用重新爬取小说目录.')else:print('json文件不存在')# 爬取小说目录spider_novel_mulu(req_dict)# 读取json文件with open(json_name, 'r') as f:data_str = f.read()# 转换为字典容器mulu_dict = json.loads(data_str)# 在列表中查找指定元素的下标,未完成标志下标flag_index = mulu_dict['flag'].index('0')print(flag_index)# 章节总数chap_len = len(mulu_dict['chap_url'])# 在列表中查找指定元素的下标print('章节总数:', chap_len)# 截图目录screenshot_dir = os.path.join(os.path.dirname(__file__), 'screenshot')if not os.path.exists(screenshot_dir):os.makedirs(screenshot_dir)print('打开浏览器驱动')open_driver()# 循环读取章节for chap_id in range(flag_index, chap_len):print('chap_id : ', chap_id)# 章节urlchap_url = mulu_dict['chap_url'][chap_id]# 截图目录,根据章节ID分类保存chap_id_dir = os.path.join(screenshot_dir, str(chap_id))if not os.path.exists(chap_id_dir):os.makedirs(chap_id_dir)# 打开网址网页print('打开网址网页')driver.get(chap_url)# 等待6秒启动完成driver.implicitly_wait(6)print('随机休眠')# 随机休眠 暂停0-2秒的整数秒time.sleep(random.randint(0, 2))# 章节分页url列表初始化page_href_list = []# 根据url地址获取网页信息chap_rst = get_html_by_webdriver(chap_url)time.sleep(3)if chap_rst[0] != 1:# 跳出循环爬取breakchap_html_str = chap_rst[3][0]# 使用BeautifulSoup解析网页数据chap_soup = BeautifulSoup(chap_html_str, "html.parser")# 章节内容分页数和分页url# 获取分页页码标签下的href元素取出page_href_list_tmp = chap_soup.select("div#PageSet > a")all_page_cnt = len(page_href_list_tmp)print("分页页码链接数量:" + str(all_page_cnt))# 去除最后/后面数字+.htmltmp_chap_url = re.sub(r'(\d+\.html)', '', chap_url)for each in page_href_list_tmp:if len(each) > 0:chap_url = tmp_chap_url + str(each.get('href'))print("拼接小说章节分页url链接:" + chap_url)# 判断是否已经存在列表中if not chap_url in page_href_list:page_href_list.append(chap_url)print("分页url链接列表:" + str(page_href_list))# 网页长宽最大化,保证截图是完整的,不会出现滚动条S = lambda X: driver.execute_script('return document.body.parentNode.scroll' + X)driver.set_window_size(S('Width'), S('Height'))# 章节页码,首页page_num = 1# 章节内容截图image_file = os.path.join(chap_id_dir, str(page_num) + '.png')# 元素定位chap_content_element = driver.find_element(By.ID, 'content')print(chap_content_element)# 元素截图chap_content_element.screenshot(image_file)# 分页列表大于0if len(page_href_list) > 0:for chap_url_page in page_href_list:print("chap_url_page:" + chap_url_page)time.sleep(3)# 打开网址网页print('打开网址网页')driver.get(chap_url_page)# 等待6秒启动完成driver.implicitly_wait(6)print('随机休眠')# 随机休眠 暂停0-2秒的整数秒time.sleep(random.randint(0, 2))# 章节页码page_num += 1# 章节内容截图image_file = os.path.join(chap_id_dir, str(page_num) + '.png')# 元素定位chap_content_element = driver.find_element(By.ID, 'content')print(chap_content_element)# 元素截图chap_content_element.screenshot(image_file)# 爬取明细章节内容截图成功后,更新对应标志为-2-截图已完成mulu_dict['flag'][chap_id] = '2'print('关闭浏览器驱动')close_driver()# 转换为json字符串json_str = json.dumps(mulu_dict)# 再次写入json文件,保存更新处理完标志with open(json_name, 'w', encoding="utf-8") as json_file:json_file.write(json_str)print("再次写入json文件,保存更新处理完标志")# 返回容器return [1, '000000', '爬取小说内容截图成功', [None]]except Exception as e:print('关闭浏览器驱动')close_driver()# 转换为json字符串json_str = json.dumps(mulu_dict)# 再次写入json文件,保存更新处理完标志with open(json_name, 'w', encoding="utf-8") as json_file:json_file.write(json_str)print("再次写入json文件,保存更新处理完标志")print("爬取小说内容异常," + str(e))return [0, '999999', "爬取小说内容截图异常," + str(e), [None]]

第二步:通过OCR接口识别截图

结合之前《PaddleOCR学习笔记3-通用识别服务》和《selenium自动化测试-获取动态页面小说》相关的文章代码,改造下,封装成一个新方法,通过OCR接口识别小说网页内容截图,然后写入文件保存。

依旧采用拆分步骤细化功能模块封装方法编写代码,便于后续扩展功能模块,代码中缺少的封装方法代码,详情参考之前的《selenium自动化测试》文章。

# 模拟http请求
def requests_http(file_path, file_name, url):full_file_path = os.path.join(file_path, file_name)# 请求参数,文件名req_data = {'upload_file': open(full_file_path, 'rb')}# 模拟http请求rsp_data = requests.post(url, files=req_data)# print(rsp_data.text)result_dict = json.loads(rsp_data.text)# print(result_dict)return result_dictdef spider_novel_content_by_ocr(req_dict):'''@方法名称: 通过OCR接口获取小说章节明细内容文字@中文注释: 读取章节列表json文件,通过OCR接口获取小说章节明细内容文字,保存到文本文件@入参:@param req_dict dict 请求容器@出参:@返回状态:@return 0 失败或异常@return 1 成功@返回错误码@返回错误信息@param rsp_dict dict 响应容器@作    者: PandaCode辉@weixin公众号: PandaCode辉@创建时间: 2023-09-26@使用范例: spider_novel_content_by_ocr(req_dict)'''try:if (not type(req_dict) is dict):return [0, "111111", "请求容器参数类型错误,不为字典", [None]]# 章节目录文件名json_name = req_dict['novel_name'] + '.json'# 检查文件是否存在if os.path.isfile(json_name):print('json文件存在,不用重新爬取小说目录.')else:print('json文件不存在')# 爬取小说目录spider_novel_mulu(req_dict)# 读取json文件with open(json_name, 'r') as f:data_str = f.read()# 转换为字典容器mulu_dict = json.loads(data_str)"""关于open()的mode参数:'r':读'w':写'a':追加'r+' == r+w(可读可写,文件若不存在就报错(IOError))'w+' == w+r(可读可写,文件若不存在就创建)'a+' ==a+r(可追加可写,文件若不存在就创建)对应的,如果是二进制文件,就都加一个b就好啦:'rb'  'wb'  'ab'  'rb+'  'wb+'  'ab+'"""file_name = req_dict['novel_name'] + '.txt'# 在列表中查找指定元素的下标,2-截图完成,标志下标flag_index = mulu_dict['flag'].index('2')print(flag_index)# 2-截图完成,标志下标为0,则为第一次爬取章节内容,否则已经写入部分,只能追加内容写入文件# 因为章节明细内容很多,防止爬取过程中间中断,重新爬取,不用重复再爬取之前成功写入的数据if flag_index == 0:# 打开文件,首次创建写入fo = open(file_name, "w+", encoding="utf-8")else:# 打开文件,再次追加写入fo = open(file_name, "a+", encoding="utf-8")# 章节总数chap_len = len(mulu_dict['chap_url'])# 在列表中查找指定元素的下标print('章节总数:', chap_len)# 截图目录screenshot_dir = os.path.join(os.path.dirname(__file__), 'screenshot')# 循环读取章节for chap_id in range(flag_index, chap_len):# 识别成功标志succ_flag = False# 章节标题chap_title = mulu_dict['chap_title'][chap_id]print('chap_id : ', chap_id)# # 写入文件,章节标题fo.write("\n" + chap_title + "\r\n")# 截图目录,根据章节ID分类保存chap_id_dir = os.path.join(screenshot_dir, str(chap_id))# 列出目录下的所有文件和文件夹file_list = os.listdir(chap_id_dir)# 章节目录下文件列表大于0if len(file_list) > 0:for file_name in file_list:print("file_name:" + file_name)time.sleep(3)url = "http://127.0.0.1:5000/upload/"# 模拟http请求result_dict = requests_http(chap_id_dir, file_name, url)print(result_dict)# 识别成功if result_dict['error_code'] == '000000':succ_flag = Trueresult_list = result_dict['result']for data in result_list:print(data['text'])# 将识别结果,逐行写入文件,章节内容fo.write(data['text'] + "\n")else:succ_flag = Falseprint('识别失败异常.')# 识别成功则更新if succ_flag:# 爬取明细章节内容成功后,更新对应标志为-1-已完成mulu_dict['flag'][chap_id] = '1'print('关闭浏览器驱动')close_driver()# 关闭文件fo.close()print("循环爬取明细章节内容,写入文件完成")# 转换为json字符串json_str = json.dumps(mulu_dict)# 再次写入json文件,保存更新处理完标志with open(json_name, 'w', encoding="utf-8") as json_file:json_file.write(json_str)print("再次写入json文件,保存更新处理完标志")# 返回容器return [1, '000000', '爬取小说内容成功', [None]]except Exception as e:print('关闭浏览器驱动')close_driver()# 关闭文件fo.close()# 转换为json字符串json_str = json.dumps(mulu_dict)# 再次写入json文件,保存更新处理完标志with open(json_name, 'w', encoding="utf-8") as json_file:json_file.write(json_str)print("再次写入json文件,保存更新处理完标志")print("爬取小说内容异常," + str(e))return [0, '999999', "爬取小说内容异常," + str(e), [None]]

第三步:运行效果

第四步:总结

目前很多网站都有基本的反爬策略,常见就是验证码、JS参数加密这两种。
爬虫本身会对网站增加一定的压力,所以也应该合理设定爬取速率,尽量避免对目标网站造成麻烦,影响网站正常使用,一定注意自己爬虫的姿势。

敬畏法律,遵纪守法,从我做起。

 最后说明:上述文章仅供学习参考,请勿用于商业用途,感谢阅读。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/142878.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode算法二叉树—117. 填充每个节点的下一个右侧节点指针 II(层序遍历/队列)

目录 117. 填充每个节点的下一个右侧节点指针 II - 力扣(LeetCode) 题解: 代码: 运行结果: ​编辑 给定一个二叉树: struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指…

2023-09-21 buildroot linux 查看应用的log打印信息,命令cat /var/log/messages

一、应用会调用syslog 把打印信息输出到串口,debug 串口会打印kernel的log和上层应用的的log。 二、linux 命令cat /var/log/messages查看应用log

【常用代码15】文字单词超出强制分割换行,word-break: break-all;和word-wrap: break-word;的区别

项目场景: 提示:这里简述项目相关背景: 文件上传后显示文件名,名称过长,超出div 有些文件名如下图 问题描述 提示:这里描述项目中遇到的问题: 一般图片上传,要展示文件名&#x…

基于Springboot实现毕业生信息招聘平台管理系统演示【项目源码+论文说明】分享

基于Springboot实现毕业生信息招聘平台管理系统演示 摘要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 毕业生信息招聘平台,主要的模块包括查看管理员;首页、个人中心、企…

预制菜行业数据分析(京东数据挖掘)

最近一段时间,关于预制菜进校园事件的讨论热度高涨。而这两天,核酸大王“张核子”转行开预制菜公司卖方便米饭的消息又被传出,直接让预制菜市场饱受关注。 “预制菜是近两年的风口”,这个结论鲸参谋早在以往的内容中专门讨论过&a…

自学WEB后端03-Node.js 语法

学习后端路线: JavaScript 基础语法 Node,js 内置 API 模块 (fs、 path、 http等) 第三方 API 模块 (express、mysql等) 今天主要回顾下Node.js 语法 Node.js 是基于 Chrome V8 引擎的 JavaScript 运行环境,它提供了一种能够在服务器端运行 JavaScr…

前端求职指南

简历求职指南 为什么没有面试? 1、简历写的不好 2、简历投递不好 简历的定义是什么? 是求职者向未来雇主展示自己专业技能和职业素养的自我推销工具,以找到工作为目的。 什么时候改简历? 每半年或一年更新一次工作中的成长 再工…

Open3D 进阶(12)PCA拟合平面

目录 一、算法原理二、代码实现三、结果展示四、优秀博客本文由CSDN点云侠原创,原文链接。爬虫网站自重。 一、算法原理 本文实现基于主成分分析方法的最小二乘拟合平面。原理如下: 针对整个点云 P = { p i }

torch.sum()——dim参数

dim指在dim的这个维度上,对tesnor 进行求和,如果keepdim(保持维度)False,返回结果会删去dim所指的这个维度。以下面的例子分析dim的参数~ torch.tensor([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]) print(…

如何兼顾性能+实时性处理缓冲数据?

们经常会遇到这样的数据处理应用场景:我们利用一个组件实时收集外部交付给它的数据,并由它转发给一个外部处理程序进行处理。考虑到性能,它会将数据存储在本地缓冲区,等累积到指定的数量后打包发送;考虑到实时性&#…

Linux Ubuntu配置Git的方法

本文介绍在Linux操作系统的Ubuntu版本中,配置分布式开源版本控制系统Git,随后基于Git克隆GitHub中项目的代码的详细方法。 在之前的文章分布式版本控制系统Git的下载、安装与使用其复制GitHub项目代码的方法(https://blog.csdn.net/zhebushib…

区块链实验室(27) - 区块链+物联网应用案例

分享最新的区块链物联网应用案例:HPCLS-BC

HTML详细基础(一)H5标签入门

本帖为B站网课黑马程序员的学习笔记,总结了H5最核心的概念性质,适用于初学者或者应对期末考试的群体~ 目录 一.Html简介 二.开发工具 三.基础标签 1.核心基础 2.标题标签 3.段落标签 ​编辑 4.文本格式标签 5.盒子标签 6.图片标签 一.Html简介 H…

索引的数据结构

文章目录 索引的数据结构1. 为什么使用索引2 索引及其优缺点2.1 索引概述2.2 索引优点 3. InnoDB中索引的推演 索引的数据结构 1. 为什么使用索引 索引是存储引擎用于快速找到数据记录的一种数据结构,如书的目录,通过目录找到对应文章的页码&#xff0…

ternsor合并与分割

拼接:拆分:Cat、StackSplit、Chunk 1、cat(concat) 统计班级学生成绩: [class1-4, students, scores] [class5-9, students, scores] 将这九名学生的成绩进行合并 a torch.rand(4, 32, 8) b torch.rand(5, 32, 8…

特种设备安全监测终端,降低安全隐患风险!

特种设备运行关系到人民生命财产安全,关系到经济健康发展,关系到社会的稳定。有关特种设备的事故基本都发生在使用过程中,因此,使用过程的安全管理是特种设备的管理重点。针对国内特种设备本身存在事故隐患及安装、维修、操作、指…

知识工程---neo4j 5.12.0+GDS2.4.6安装

(已安装好neo4j community 5.12.0) 一. GDS下载 jar包下载地址:https://neo4j.com/graph-data-science-software/ 下载得到一个zip压缩包,解压后得到jar包。 二. GDS安装及配置 将解压得到的jar包放入neo4j安装目录下的plugi…

java中使用redis2个库并支持Redis哈希表

一个redis实例,默认包含16个库,序号从0到15。在redis命令行中,可以用select 序号来切换。我最近在做的一个项目中,需要使用redis的2个库。一个是由其他子系统写入,web后端(java)只读取&#xff…

Selenium自动化测试 —— 通过cookie绕过验证码的操作!

验证码的处理 对于web应用,很多地方比如登录、发帖都需要输入验证码,类型也多种多样;登录/核心操作过程中,系统会产生随机的验证码图片,进行验证才能进行后续操作 解决验证码的方法如下: 1、开发做个万能…