当前位置: 首页 > article >正文

Python 之 selenium 打开浏览器指定端口进行接续操作

一般使用 selenium 进行数据爬取时,常用处理流程是让 selenium 从打开浏览器开始,完成全流程的所有操作。但是有时候,我们希望用户先自己打开浏览器进入指定网页,完成登录认证等一系列操作之后(比如用户、密码、短信验证码及各种难处理的图形验证码之类),再让 selenium 从登录后的页面进行接续操作爬取数据。那么如何才能将前后操作接续起来呢?

常规操作

常规操作一般使用下面的这种方式,设置初始参数后直接使用 get 方法去打开网页。

from selenium import webdriverclass DriverClass:def __init__(self):self.driver = self._init_driver()def _init_driver(self):try:option = webdriver.ChromeOptions()option.add_experimental_option('excludeSwitches', ['enable-automation'])option.add_experimental_option('useAutomationExtension', False)prefs = dict()prefs['credentials_enable_service'] = Falseprefs['profile.password_manager_enable'] = Falseprefs['profile.name'] = "Person 1"option.add_experimental_option('prefs', prefs)option.add_argument('--disable-gpu')option.add_argument("--disable-blink-features=AutomationControlled")option.add_argument('--user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"')option.add_argument('--no-sandbox')option.add_argument('ignore-certificate-errors')driver = webdriver.Chrome(r"./driver/chromedriver.exe", options=option)driver.implicitly_wait(2)driver.maximize_window()return driverexcept Exception as e:raise edef get_driver(self) -> webdriver.Chrome:if isinstance(self.driver, webdriver.Chrome):return self.driverraise Exception('初始化浏览器失败')if __name__ == '__main__':dc = DriverClass()driver = dc.get_driver()print(driver)driver.get("https://www.baidu.com")

接续操作

接续操作主要通过在打开浏览器时,都设置相同的接口来完成前后的衔接(不然 selenium 不知道要从哪个浏览器页面进行接续)。

用户打开浏览器

用户手动打开浏览器时,指定对应的端口(这里设置的是 9527)及数据目录(自己自定义自定一个)。

C:\Program Files\Google\Chrome\Application>chrome.exe --remote-debugging-port=9527 --user-data-dir="E:\lky_project\tmp_project\handle_qcc_data\\chrome_user_data"

执行完上面的命令以后,会打开一个新的浏览器页面。

打开浏览器后,用户可以手动输入相应页面,完成相应的用户登录认证等操作。 

程序接续浏览器

selenium 通过增加下面的配置参数

option.add_experimental_option("debuggerAddress", "127.0.0.1:9527")

来打开并接续处理用户已经打开的指定端口的浏览器。之后,程序就可以通过浏览器句柄去接续处理后续的任务了。

driver_class.py

from selenium import webdriverclass DriverClass:def __init__(self):self.driver = self._init_driver()def _init_driver(self):try:option = webdriver.ChromeOptions()# option.add_experimental_option('excludeSwitches', ['enable-automation'])# option.add_experimental_option('useAutomationExtension', False)# prefs = dict()# prefs['credentials_enable_service'] = False# prefs['profile.password_manager_enable'] = False# prefs['profile.name'] = "Person 1"# option.add_experimental_option('prefs', prefs)option.add_argument('--disable-gpu')option.add_argument("--disable-blink-features=AutomationControlled")option.add_argument('--user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"')option.add_argument('--no-sandbox')option.add_argument('ignore-certificate-errors')option.add_experimental_option("debuggerAddress", "127.0.0.1:9527")driver = webdriver.Chrome(r"./driver/chromedriver.exe", options=option)driver.implicitly_wait(2)# driver.maximize_window()return driverexcept Exception as e:raise edef get_driver(self) -> webdriver.Chrome:if isinstance(self.driver, webdriver.Chrome):return self.driverraise Exception('初始化浏览器失败')if __name__ == '__main__':dc = DriverClass()driver = dc.get_driver()print(driver)# 程序使用接续后的浏览器句柄 driver 完成后续操作

注意事项

注意看,我上面的接续操作函数,有一部分的参数设置是注释掉的。这是因为接续是从已经打开的浏览器接收继续进行操作,有部分的参数在用户打开浏览器的时候就已经设定了,所以不再支持通过接续的方式继续重复设置。

实战示例

比如在手动打开指定 9527 端口的浏览器后,登录企查查进入高级搜索,然后使用程序获取具有相应资质的企业数目(操作太频繁可能触发校验或封号,请谨慎操作!),最后生成结果文件 data.json(中途可能会异常中断,可以做成下面这种利用 data.json 实现的断点续查的方式,这样,后续再次运行也只会查询未查询过的资质数据)。

driver_class.py 用上面的就可以。

main.py

import json
import re
import timefrom selenium.webdriver.common.by import By
from driver_class import DriverClassdc = DriverClass()
driver = dc.get_driver()
xpath_prefix = '//div/div/div/div/span[text()="资质证书"]/following-sibling::div'def checkbox_select(element_checkbox):"""复选框选中"""class_attribute = element_checkbox.get_attribute("class")if "checked" not in class_attribute:element_checkbox.find_element(By.XPATH, './span[@class="qccd-tree-checkbox-inner"]').click()def checkbox_unselect(element_checkbox):"""复选框取消选中"""class_attribute = element_checkbox.get_attribute("class")if "checked" in class_attribute:element_checkbox.find_element(By.XPATH, './span[@class="qccd-tree-checkbox-inner"]').click()def get_amount(element_checkbox):"""获取对应复选框对应的企业数目"""checkbox_select(element_checkbox)xpath_confirm = xpath_prefix + '/div/div/div/div/div[text()="确定"]'driver.find_element(By.XPATH, xpath_confirm).click()time.sleep(0.5)try:xpath_result = '//div/div/div[@class="search-btn limit-svip"]'result = str(driver.find_element(By.XPATH, xpath_result).text)except Exception as e:print(f"异常: {str(e)}")result = "0"result = result.replace(",", "")match_object = re.search("(\d+)", result)amount = match_object.group(1)print(f"数目:{amount}")# 清除结果,避免点击选择项时误点击关闭xpath_clear = '//div/div/a[contains(text(), "清除")]'try:driver.find_element(By.XPATH, xpath_clear).click()except:passxpath_select = xpath_prefix + '[@class="trigger-container"]'driver.find_element(By.XPATH, xpath_select).click()time.sleep(0.2)checkbox_unselect(element_checkbox)return amountdef extend_options():"""展开折叠项并获取数据,只展开三层"""# json.dump(data, open("data.json", 'w', encoding="utf-8"), indent=2, ensure_ascii=False)try:data = json.load(open("data.json", encoding="utf-8"))except:data = {}try:xpath_first_class = xpath_prefix + '//div/ul/li[@role="treeitem"]'# xpath_first_class = xpath_prefix + '//div/ul/li/span[contains(@class, "qccd-tree-switcher")]'first_item_list = driver.find_elements(By.XPATH, xpath_first_class)for item_li in first_item_list:text_dk1 = item_li.find_element(By.XPATH, './span/span/div/span[@class="text-dk"]').textdata[text_dk1] = data.get(text_dk1, {})print(f"{text_dk1}")switcher = item_li.find_element(By.XPATH, './span[contains(@class, "qccd-tree-switcher")]')class_attribute = switcher.get_attribute("class")element_checkbox = item_li.find_element(By.XPATH, './span[contains(@class, "checkbox")]')if "close" in class_attribute:switcher.click()time.sleep(0.1)elif "noop" in class_attribute:# 当前节点没有子节点if not data[text_dk1]:amount = get_amount(element_checkbox)data[text_dk1] = amountcontinue# 点开以后,下层级的 ul/li 会展示出来second_item_list = item_li.find_elements(By.XPATH, "./ul/li")for second_item_li in second_item_list:text_dk2 = second_item_li.find_element(By.XPATH, './span/span/div/span[@class="text-dk"]').textdata[text_dk1][text_dk2] = data[text_dk1].get(text_dk2, {})print(f"--{text_dk2}")switcher = second_item_li.find_element(By.XPATH, './span[contains(@class, "qccd-tree-switcher")]')class_attribute = switcher.get_attribute("class")element_checkbox = second_item_li.find_element(By.XPATH, './span[contains(@class, "checkbox")]')if "close" in class_attribute:switcher.click()time.sleep(0.1)elif "noop" in class_attribute:# 当前节点没有子节点if not data[text_dk1][text_dk2]:amount = get_amount(element_checkbox)data[text_dk1][text_dk2] = amountcontinue# 点开以后,下层级的 ul/li 会展示出来third_item_list = second_item_li.find_elements(By.XPATH, "./ul/li")for third_item_li in third_item_list:text_dk3 = third_item_li.find_element(By.XPATH, './span/span/div/span[@class="text-dk"]').textdata[text_dk1][text_dk2][text_dk3] = data[text_dk1][text_dk2].get(text_dk3, {})print(f"----{text_dk3}")switcher = third_item_li.find_element(By.XPATH, './span[contains(@class, "qccd-tree-switcher")]')class_attribute = switcher.get_attribute("class")# 到第三层时,不再展开,直接选择复选框element_checkbox = third_item_li.find_element(By.XPATH, './span[contains(@class, "checkbox")]')if not data[text_dk1][text_dk2][text_dk3]:amount = get_amount(element_checkbox)data[text_dk1][text_dk2][text_dk3] = amountexcept Exception as e:raise efinally:json.dump(data, open("data.json", 'w', encoding="utf-8"), indent=2, ensure_ascii=False)def spider_data():# 尝试关闭资质证书选择框、清除所选项xpath_close = xpath_prefix + '/div/div/div/a[@class="nclose"]'xpath_clear = '//div/div/a[contains(text(), "清除")]'try:driver.find_element(By.XPATH, xpath_close).click()except:passtry:driver.find_element(By.XPATH, xpath_clear).click()except:pass# 点击资质证书选择框xpath_select = xpath_prefix + '[@class="trigger-container"]'driver.find_element(By.XPATH, xpath_select).click()time.sleep(2)extend_options()# 取消按钮xpath_cancel = xpath_prefix + '/div/div/div/div/div[text()="取消"]'# 确定按钮xpath_confirm = xpath_prefix + '/div/div/div/div/div[text()="确定"]'driver.find_element(By.XPATH, xpath_confirm).click()if __name__ == '__main__':spider_data()

最后可以得到生成的 data.json 文件如下:

{"建筑业资质": {"工程设计资质证书": {"工程设计专项资质": "26329","建筑工程设计事务所": "356","工程设计行业资质": "4487","工程设计专业资质": "19902","工程设计综合资质": "98"},"工程勘察资质证书": {"工程勘察综合资质": "377","工程勘察专业资质": "7464","工程勘察劳务资质": "3019"},
...},"食品农产品认证": {"有机产品(OGA)": "49868","良好农业规范(GAP)": "6449","食品质量认证(酒类)": "151","绿色食品认证": "34723","绿色市场认证": "318","无公害农产品": "31067","食品安全管理体系认证": "72075","危害分析与关键控制点认证": "51844","乳制品生产企业良好生产规范认证": "445","乳制品生产企业危害分析与关键控制点(HACCP)体系认证": "570","饲料产品": "85"},"其他资质": {"办学许可证": "192010","代理记账许可证书": "34588","会计师事务所执业证书": "12252","DOC证书": "982","SMC证书": "1886","名特优新农产品证书": "1818","招投标类综合资质": "36317","区块链信息服务备案": "2765","医疗机构执业许可证": "570877","CCC工厂认证": "16154","卫生许可证": "3244"}
}

相关文章:

Python 之 selenium 打开浏览器指定端口进行接续操作

一般使用 selenium 进行数据爬取时,常用处理流程是让 selenium 从打开浏览器开始,完成全流程的所有操作。但是有时候,我们希望用户先自己打开浏览器进入指定网页,完成登录认证等一系列操作之后(比如用户、密码、短信验…...

MySQL Explain 中 Type 与 Extra 字段详解

引言 在数据库性能调优过程中,理解执行计划(EXPLAIN)的输出信息至关重要。MySQL 的 EXPLAIN 命令能够帮助开发者分析查询的执行路径和效率,其中 Type 和 Extra 字段提供了关键的执行细节。Type 字段表示访问类型,反映…...

不用服务器转码,Web端如何播放RTSP视频流?

在物联网、智慧城市、工业互联网等新兴技术浪潮下,实时视频流(如RTSP协议)作为安防监控、生产巡检、远程协作等场景的核心数据载体,其价值愈发凸显。然而,一个长期困扰行业的痛点始终存在——‌如何在Web浏览器中直接播…...

如何开发一款 Chrome 浏览器插件

Chrome是由谷歌开发的网页浏览器,基于开源软件(包括WebKit和Mozilla)开发,任何人都可以根据自己需要使用、修改或增强它的功能。Chrome凭借着其优秀的性能、出色的兼容性以及丰富的扩展程序,赢得了广大用户的信任。市场…...

GitHub打开缓慢甚至失败的解决办法

在C:\Windows\System32\drivers\etc的hosts中增加如下内容: 20.205.243.166 github.com 199.59.149.236 github.global.ssl.fastly.net185.199.109.153 http://assets-cdn.github.com 185.199.108.153 http://assets-cdn.github.com 185.199.110.153 http://asset…...

18前端项目----Vue项目收尾优化|重要知识

收尾/知识点汇总 项目收尾二级路由未登录全局路由守卫路由独享守卫图片懒加载路由懒加载打包上线 重要知识点汇总组件通信方式1. props2. 自定义事件3. 全局事件总线4. 订阅与发布pubsub5. Vuex6. 插槽 sync修饰符attrs和listeners属性children和parent属性mixin混入作用域插槽…...

仿RabbitMQ 模拟实现消息队列

文章目录 项目项目介绍开发环境技术选型 开始项目前第三方框架内容介绍muduo搭建服务端,客户端服务端:客户端:makefile muduo库protobuf通信服务端:客户端 sqlitegtest线程池future 认识,async使用promis使用package_t…...

基于Qt的app开发第八天

写在前面 笔者是一个大一下计科生,本学期的课程设计自命题完成一个督促学生自律的打卡软件,目前已经完成了待办和打卡部分功能,本篇要完成规划板块不需要存储就能实现的功能 需求分析 这一板块内容相比前两个板块还有一些特殊,因…...

Springboot之类路径扫描

SpringBoot框架中默认提供的扫描类为&#xff1a;ClassPathBeanDefinitionScanner。 webFlux框架中借助RepositoryComponentProvider扫描符合条件的Repository。 public class ClassPathScanningCandidateComponentProvider{private final List<TypeFilter> includeFilt…...

PNG图片转icon图标Python脚本(简易版) - 随笔

摘要 在网站开发或应用程序设计中&#xff0c;常需将高品质PNG图像转换为ICO格式图标。本文提供一份高效Python解决方案&#xff0c;利用Pillow库实现透明背景完美保留的格式转换。 源码示例 from PIL import Imagedef convert_png_to_ico(png_path, ico_path, size):"…...

数据分析-图2-图像对象设置参数与子图

from matplotlib import pyplot as mp mp.figure(A figure,facecolorgray) mp.plot([0,1],[1,2]) mp.figure(B figure,facecolorlightgray) mp.plot([1,2],[2,1]) #如果figure中标题已创建&#xff0c;则不会新建窗口&#xff0c; #而是将旧窗口设置为当前窗口 mp.figure(A fig…...

查询公网IP地址的方法:查看自己是不是公网ip,附内网穿透外网域名访问方案

本地搭建服务并提供互联网连接时&#xff0c;较为传统的方法是使用公网IP地址。因此&#xff0c;如何查询本地自己是不是公网IP&#xff0c;是必须要掌握的一种技巧。当面对确实无公网IP时&#xff0c;则可以通过内网穿透方案&#xff0c;如nat123网络映射工具&#xff0c;将本…...

MVCC:数据库并发控制的利器

在并发环境下&#xff0c;数据库需要处理多个事务同时访问和修改数据的情况。为了保证数据的一致性和隔离性&#xff0c;数据库需要采用一些并发控制机制。MVCC (Multi-Version Concurrency Control&#xff0c;多版本并发控制) 就是一种常用的并发控制技术&#xff0c;它通过维…...

Redis学习打卡-Day1-SpringDataRedis、有状态无状态

Redis的Java客户端 Jedis 以 Redis 命令作为方法名称&#xff0c;学习成本低&#xff0c;简单实用。Jedis 是线程不安全的&#xff0c;并且频繁的创建和销毁连接会有性能损耗&#xff0c;因此推荐使用 Jedis 连接池代替Jedis的直连方式。 lettuce Lettuce是基于Netty实现的&am…...

【行为型之访问者模式】游戏开发实战——Unity灵活数据操作与跨系统交互的架构秘诀

文章目录 &#x1f9f3; 访问者模式&#xff08;Visitor Pattern&#xff09;深度解析一、模式本质与核心价值二、经典UML结构三、Unity实战代码&#xff08;游戏物品系统&#xff09;1. 定义元素与访问者接口2. 实现具体元素类3. 实现具体访问者4. 对象结构管理5. 客户端使用 …...

Shell脚本实践(修改文件,修改配置文件,执行jar包)

1、前言 需要编写一个shell脚本支持 1、修改.so文件名 2、修改配置文件 3、执行jar包 2、代码解析 2.1、修改.so文件名 so_file_dir="/opt/casb/xxx/lib" # 处理.so文件 cd "$so_file_dir" || { echo "错误: 无法进入目录 $so_file_dir"; exit …...

React Native矢量图标全攻略:从入门到自定义iconfont的高级玩法

“你知道吗?在React Native应用中,仅仅通过一行代码就能召唤出上千个精美矢量图标,甚至还能把设计师精心制作的iconfont完美嵌入——但90%的开发者居然还在用图片方案!” 当我第一次发现同事的APP安装包比我的小了2.3MB,仅仅是因为他正确使用了react-native-vector-icons时…...

x-IMU matlab zupt惯性室内定位算法

基于x-IMU的ZUPT&#xff08;Zero Velocity Update&#xff0c;零速更新&#xff09;惯性室内定位算法是一种结合了惯性测量单元&#xff08;IMU&#xff09;数据和零速检测技术的室内定位方法。该算法通过检测行人静止状态下的零速区间&#xff0c;对惯性导航系统&#xff08;…...

hbase shell的常用命令

一、hbase shell的基础命令 # 版本号查看 [rootTest-Hadoop-NN-01 hbase]$ ./bin/hbase version HBase 2.4.0 Source code repository git://apurtell-ltm.internal.salesforce.com/Users/apurtell/src/hbase revision282ab70012ae843af54a6779543ff20acbcbb629# 客户端登录 […...

在企业级项目中高效使用 Maven-mvnd

1、引言 1.1 什么是 Maven-mvnd? Maven-mvnd 是 Apache Maven 的一个实验性扩展工具(也称为 mvnd),基于守护进程(daemon)模型构建,目标是显著提升 Maven 构建的速度和效率。它由 Red Hat 推出,通过复用 JVM 进程来减少每次构建时的启动开销。 1.2 为什么企业在构建过…...

iOS瀑布流布局的实现(swift)

在iOS开发中&#xff0c;瀑布流布局&#xff08;Waterfall Flow&#xff09;是一种常见的多列不等高布局方式&#xff0c;适用于图片、商品展示等场景。以下是基于UICollectionView实现瀑布流布局的核心步骤和优化方法&#xff1a; 一、实现原理 瀑布流的核心在于动态计算每个…...

Spring Spring Boot 常用注解整理

Spring & Spring Boot 常用注解整理 先理解核心概念&#xff1a;什么是注解&#xff08;Annotation&#xff09;&#xff1f;第一部分&#xff1a;IOC&#xff08;控制反转&#xff09;和 DI&#xff08;依赖注入&#xff09;1. Component2. Service, Repository, Controll…...

c#建筑行业财务流水账系统软件可上传记账凭证财务管理系统签核功能

# financial_建筑行业 建筑行业财务流水账系统软件可上传记账凭证财务管理系统签核功能 # 开发背景 软件是给岳阳客户定制开发一款建筑行业流水账财务软件。提供工程签证单、施工日志、人员出勤表等信息记录。 # 财务管理系统功能描述 1.可以自行设置记账科目&#xff0c;做凭…...

让 Cursor 教我写 MCP Client

文章目录 1. 写在最前面2. 动手实现一个 MCP Client2.1 How 天气查询 Client2.1.1 向 Cursor 提问的艺术2.1.2 最终成功展示2.1.3 client 的代码 3. MCP 协议核心之一总结3.1 SSE vs WebSocket 4. 碎碎念5. 参考资料 1. 写在最前面 学习了 MCP Server 的实现后&#xff0c;刚好…...

反射, 注解, 动态代理

文章目录 单元测试什么是单元测试咱们之前是如何进行单元测试的&#xff1f; 有啥问题 &#xff1f;现在使用方法进行测试优点Junit单元测试的使用步骤删除不需要的jar包总结 反射认识反射、获取类什么是反射反射具体学什么&#xff1f;反射第一步&#xff1a;或者Class对象 获…...

vue vite 无法热更新问题

一、在vue页面引入组件CustomEmployeesDialog&#xff0c;修改组件CustomEmployeesDialog无法热更新 引入方式&#xff1a; import CustomEmployeesDialog from ../dialog/customEmployeesDialog.vue 目录结构&#xff1a; 最后发现是引入import时&#xff0c;路径大小写与目…...

【CustomPagination:基于Vue 3与Element Plus的高效二次封装分页器】

CustomPagination&#xff1a;基于Vue 3与Element Plus的高效二次封装分页器 在现代Web应用开发中&#xff0c;分页是处理大量数据列表时不可或缺的功能。Element Plus等UI库提供了基础的分页组件&#xff0c;但在大型项目中&#xff0c;为了追求极致的用户体验和视觉统一&…...

kafka connect 大概了解

kafka connect Introduction Kafka Connect is the component of Kafka that provides data integration between databases, key-value stores, search indexes, file systems, and Kafka brokers. kafka connect 是一个框架&#xff0c;用来帮助集成其他系统的数据到kafka…...

UniApp 在华为三折叠屏中的适配问题与最佳解决方案(rpx 实战指南)

随着折叠屏设备的普及&#xff0c;如华为 Mate Xs、Mate X3 等多形态设备越来越常见&#xff0c;开发者在 UniApp 项目中遇到的适配问题也变得复杂。本文将聚焦一个关键问题&#xff1a;在三折叠屏设备上&#xff0c;使用 px 单位造成页面显示异常&#xff0c;并给出最推荐的解…...

深度学习中的查全率与查准率:如何实现有效权衡

&#x1f4cc; 友情提示&#xff1a; 本文内容由银河易创AI&#xff08;https://ai.eaigx.com&#xff09;创作平台的gpt-4-turbo模型辅助生成&#xff0c;旨在提供技术参考与灵感启发。文中观点或代码示例需结合实际情况验证&#xff0c;建议读者通过官方文档或实践进一步确认…...