selenium单例模式下 docker-chrome 多线程并发代码

news/2024/10/23 9:30:19/文章来源:https://www.cnblogs.com/haoabcd2010/p/18494433

最近需要写爬虫,在解决docker-standalone-chrome 发现只能有一个chrome被执行。所以写了这个多线程并发控制类来管理。当模板记录下。


#! /usr/bin/env python3
import threading
import tracebackfrom loguru import logger
from selenium import webdriver
from selenium.common import WebDriverException
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
from selenium.webdriver.common.by import By
import json
from utils.configs import ScreenshotDir, ChromeUserDataDir, REMOTE_DRIVERdef options():"""默认选项"""opts = webdriver.ChromeOptions()opts.add_argument(f"user-data-dir={ChromeUserDataDir}")opts.page_load_strategy = 'eager'opts.add_experimental_option('excludeSwitches', ['enable-automation'])  # 开发者模式opts.add_argument("--disable-popup-blocking")  # 关闭操作baropts.add_argument("--blink-settings=imagesEnabled=false")  # 禁用图片opts.add_argument("--window-size=1920,1080")  # 窗口大小opts.add_argument("--no-sandbox")  # 无沙箱opts.add_argument("--disable-gpu")# opts.add_argument('--headless')  # 无头模式# opts.add_experimental_option('debuggerAddress', '127.0.0.1:9222')  # 指定serverreturn optsclass Browser:"""浏览器,线程不安全"""def __init__(self, opts=None):if not opts:opts = options()self.driver = webdriver.Remote(command_executor=REMOTE_DRIVER, options=opts)# self.driver = webdriver.Chrome(options=opts)def quit(self):try:if hasattr(self, 'driver') and hasattr(self.driver, 'quit'):self.driver.quit()self.driver = Noneexcept Exception as e:logger.error("browser quit err:{e}\ntraceback:{traceback}".format(e=e, traceback=traceback.format_exc()))def send(self, cmd, params):"""发送命令"""resource = "/session/%s/chromium/send_command_and_get_result" % self.driver.session_idurl = self.driver.command_executor._url + resourcebody = json.dumps({'cmd': cmd, 'params': params})response = self.driver.command_executor._request('POST', url, body)return response.get('value')def get(self, url) -> None:logger.info(f'browser starting open url={url}')self.driver.get(url)logger.info(f'browser open suc url={url}')def wait_by_xpath(self, path, timeout=10) -> None:try:WebDriverWait(self.driver, timeout, 1, ignored_exceptions=(WebDriverException,)).until(EC.element_to_be_clickable((By.XPATH, path)))except Exception:logger.error(f'browser wait xpath not find')def wait_by_id(self, tid, timeout=10) -> None:try:WebDriverWait(self.driver, timeout, 1, ignored_exceptions=(WebDriverException,)).until(EC.presence_of_element_located((By.ID, tid)))except Exception:logger.error(f'browser wait id not find')def save(self, path):with open(path, 'w', encoding='utf-8') as fw:fw.write(self.get_page_source())def get_page_source(self) -> str:return self.driver.page_sourcedef click(self, path):try:button = self.driver.find_element(By.XPATH, path)if button:button.click()time.sleep(2)# 跳转到新标签windows = self.driver.window_handlesself.driver.switch_to.window(windows[-1])return self.driver.current_urlelse:return ""except Exception as e:logger.error(f'browser click err={e}')def screenshot(self, name=None):full_name = 'full_page_screenshot.png'if name:full_name = namescreenshot_path = f'{ScreenshotDir}/{full_name}'self.driver.save_screenshot(screenshot_path)class BrowserManager:"""浏览器管理类,线程安全usages:with BrowserManager() as browser:browser.get(url)"""_browser = None_is_used = False_condition = threading.Condition()def __init__(self, opts=None):self.opts = optsdef __enter__(self):with BrowserManager._condition:while BrowserManager._is_used:if not BrowserManager._condition.wait(timeout=10):continueBrowserManager._is_used = Truetry:BrowserManager._browser = Browser(self.opts)except Exception as e:BrowserManager._is_used = Falseraise ereturn BrowserManager._browserdef __exit__(self, exc_type, exc_value, traceback):with BrowserManager._condition:BrowserManager._browser.quit()BrowserManager._is_used = FalseBrowserManager._condition.notify()

用法就很简单了,例如


with BrowserManager() as browser:try:browser.get(url)return browser.get_page_source()except Exception as e:logger.error(e)

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在外包干了 3 年,被强制清场了。。。

大家好,我是R哥。 今天再分享一个励志的面试辅导案例:一个深圳的兄弟,双非二本,工作 5 年+,在外包干了 3 年,结果今年被甲方强制清场了,没有赔偿,边走劳动仲裁,边学习,最终拿下还不错的自研 offer,脱离外包,太励志了。。在外包干了 3 年,被甲方清场,还没有赔偿,…

CogView3---CogView-3Plus-微调代码源码解析-四-

CogView3 & CogView-3Plus 微调代码源码解析(四) .\cogview3-finetune\sat\sgm\modules\diffusionmodules\sampling_utils.py # 导入数学库以进行数学运算 import math # 导入 PyTorch 库以进行张量操作 import torch # 从 SciPy 库导入积分函数 from scipy import integ…

CogView3---CogView-3Plus-微调代码源码解析-三-

CogView3 & CogView-3Plus 微调代码源码解析(三) .\cogview3-finetune\sat\sgm\modules\diffusionmodules\guiders.py # 导入 logging 模块,用于记录日志信息 import logging # 从 abc 模块导入 ABC 类和 abstractmethod 装饰器,用于定义抽象基类和抽象方法 from abc i…

CogView3---CogView-3Plus-微调代码源码解析-二-

CogView3 & CogView-3Plus 微调代码源码解析(二) .\cogview3-finetune\sat\sgm\models\__init__.py # 从同一模块导入 AutoencodingEngine 类,用于后续的自动编码器操作 from .autoencoder import AutoencodingEngine# 注释文本(可能是无关信息或标识符) #XuDwndGaCFo…

券后价复杂根源和解法

券后价领域划分不清楚 券后价在电商系统中是个很奇怪的存在 无论是按商品领域还是营销领域划分,它都不合适归类到这两者中间。结果就是券后价是个很不理想的拆分逻辑。 券后价可以理解是商品的价格属性,这个属性是由营销来计算控制。领域划分可以理解为商品领域,营销做计算!…

营销领域分析

用户与商品的连接用户购买商品是整个商业的基本盘。用户与商品是多对多关系,在这个基础之上就可衍生出许多行为。可以跟据商品的属性又可以设计各种运营方式。 用几个条件来归类交易产生的条件条件 人 物when 人什么时候需要商品 商品什么时候被需要why 人为什么需要商品 商品…

计数系统设计

在营销的场景里有三要素用户 商品 优惠在这三个要素里,再加一些如时间,数量,频次等变量,会演化出各种组合,使得业务变得非常灵活。各业务线为了满足业务,一般都会各自实现,且多数情况下都会重复实现,而且实现起来各地方都会产生交叉配置,交叉互斥的问题。在观察到这些…

PbootCMS授权码可以更换域名吗? 授权码丢失怎么办?

授权码可以更换域名吗?不可以:授权码是绑定特定域名的,如果需要更换域名,建议重新获取新的授权码。授权码丢失怎么办?重新获取:如果授权码丢失,可以重新访问授权页面,输入相同的域名再次获取授权码。扫码添加技术【解决问题】专注中小企业网站建设、网站安全12年。熟悉…

PbootCMS授权码是否可以用于不同域名的子域名?是否可以用于不同域名的子目录?

授权码是否可以用于不同域名的子域名?不可以:授权码是绑定特定域名的,不支持不同域名的子域名。例如,sub1.example.com 和 sub2.anotherdomain.com 需要分别获取授权码。18. 授权码是否可以用于不同域名的子目录?不可以:授权码是绑定特定域名的,不支持不同域名的子目录。…

PbootCMS验证码不显示或显示不清楚怎么办

验证码不显示或显示不清楚问题描述:后台登录时验证码不显示或显示不清楚。 解决方案:避免使用中文路径:确保所有文件和目录名称均为英文或数字。 切换PHP版本:推荐使用PHP 7.3、7.2、5.6版本。 检查文件权限:确保验证码相关文件和目录具有适当的读写权限(通常为755或644)…

值得信赖的FTP替代方案有哪些,一文带你详细了解!

FTP(文件传输协议)因其传输速度慢、安全隐患、管理复杂性、稳定性不足以及审计难题等缺陷,使得企业在寻找更高效的替代方案时显得尤为迫切。 FTP替代方案有哪些,简单了解看下吧: 1、SFTP:SFTP是建立在SSH(Secure Shell)协议之上的文件传输协议,提供了数据传输的加密和…

HTTP 2.0 新特性

HTTP 2.0 新特性HTTP 2.0 为什么使用二进制分帧?二进制协议比文本协议更加紧凑,减少占用空间 分帧层相当于将 HTTP 切分,更加灵活,比如可以对 header 帧做单独的特殊处理 分帧层有着属于自己的报文头,其中的 Stream Identity 使得操作系统具备将多个响应以及请求一一匹配的…