first commit
This commit is contained in:
commit
4890793ce5
1029 files changed
+5992
No files matched your search
@@ -0,0 +1,3 @@
|
||||
"""工具函数模块."""
|
||||
|
||||
# 使 utils 目录成为 Python 包
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,147 @@
|
||||
import logging
|
||||
import time
|
||||
from typing import Optional
|
||||
from playwright.sync_api import Page, TimeoutError as PlaywrightTimeoutError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BrowserUtils:
|
||||
"""浏览器操作工具类"""
|
||||
|
||||
@staticmethod
|
||||
def wait_for_element(page: Page, selector: str, timeout: int = 30000) -> bool:
|
||||
"""
|
||||
等待元素出现
|
||||
|
||||
Args:
|
||||
page: Playwright页面对象
|
||||
selector: CSS选择器
|
||||
timeout: 超时时间(毫秒)
|
||||
|
||||
Returns:
|
||||
bool: 成功返回True,超时返回False
|
||||
"""
|
||||
try:
|
||||
page.wait_for_selector(selector, timeout=timeout)
|
||||
return True
|
||||
except PlaywrightTimeoutError:
|
||||
logger.warning(f"等待元素超时: {selector}")
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def fill_input(
|
||||
page: Page, selector: str, text: str, clear_first: bool = True
|
||||
) -> bool:
|
||||
"""
|
||||
填充输入框
|
||||
|
||||
Args:
|
||||
page: Playwright页面对象
|
||||
selector: CSS选择器
|
||||
text: 要填充的文本
|
||||
clear_first: 是否先清除原有内容
|
||||
|
||||
Returns:
|
||||
bool: 成功返回True,失败返回False
|
||||
"""
|
||||
try:
|
||||
# 等待元素出现
|
||||
if not BrowserUtils.wait_for_element(page, selector):
|
||||
return False
|
||||
|
||||
# 如果需要先清除原有内容
|
||||
if clear_first:
|
||||
page.fill(selector, "")
|
||||
|
||||
# 填充文本
|
||||
page.fill(selector, text)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"填充输入框时出错: {str(e)}")
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def click_element(page: Page, selector: str, timeout: int = 30000) -> bool:
|
||||
"""
|
||||
点击元素
|
||||
|
||||
Args:
|
||||
page: Playwright页面对象
|
||||
selector: CSS选择器
|
||||
timeout: 超时时间(毫秒)
|
||||
|
||||
Returns:
|
||||
bool: 成功返回True,失败返回False
|
||||
"""
|
||||
try:
|
||||
# 等待元素出现
|
||||
if not BrowserUtils.wait_for_element(page, selector, timeout):
|
||||
return False
|
||||
|
||||
# 点击元素
|
||||
page.click(selector)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"点击元素时出错: {str(e)}")
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def get_text(page: Page, selector: str) -> Optional[str]:
|
||||
"""
|
||||
获取元素文本内容
|
||||
|
||||
Args:
|
||||
page: Playwright页面对象
|
||||
selector: CSS选择器
|
||||
|
||||
Returns:
|
||||
str or None: 元素文本内容或None
|
||||
"""
|
||||
try:
|
||||
# 等待元素出现
|
||||
if not BrowserUtils.wait_for_element(page, selector):
|
||||
return None
|
||||
|
||||
# 获取文本内容
|
||||
return page.text_content(selector)
|
||||
except Exception as e:
|
||||
logger.error(f"获取元素文本内容时出错: {str(e)}")
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def take_screenshot(page: Page, path: str) -> bool:
|
||||
"""
|
||||
截取屏幕截图
|
||||
|
||||
Args:
|
||||
page: Playwright页面对象
|
||||
path: 截图保存路径
|
||||
|
||||
Returns:
|
||||
bool: 成功返回True,失败返回False
|
||||
"""
|
||||
try:
|
||||
page.screenshot(path=path)
|
||||
logger.info(f"已保存截图: {path}")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"截图时出错: {str(e)}")
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def is_element_visible(page: Page, selector: str) -> bool:
|
||||
"""
|
||||
检查元素是否可见
|
||||
|
||||
Args:
|
||||
page: Playwright页面对象
|
||||
selector: CSS选择器
|
||||
|
||||
Returns:
|
||||
bool: 可见返回True,不可见返回False
|
||||
"""
|
||||
try:
|
||||
return page.is_visible(selector)
|
||||
except Exception:
|
||||
return False
|
||||
@@ -0,0 +1,57 @@
|
||||
import os
|
||||
import logging
|
||||
from logging.handlers import RotatingFileHandler
|
||||
import time
|
||||
|
||||
|
||||
def setup_logger():
|
||||
"""
|
||||
配置应用程序日志记录器
|
||||
|
||||
- 将日志输出到控制台
|
||||
- 将日志保存到文件(带有时间戳的文件名)
|
||||
- 使用轮换文件处理程序限制日志文件大小
|
||||
"""
|
||||
# 确保日志目录存在
|
||||
logs_dir = os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "logs"
|
||||
)
|
||||
os.makedirs(logs_dir, exist_ok=True)
|
||||
|
||||
# 创建时间戳日志文件名
|
||||
timestamp = time.strftime("%Y%m%d-%H%M%S")
|
||||
log_file = os.path.join(logs_dir, f"douyin_imbot_{timestamp}.log")
|
||||
|
||||
# 配置根日志记录器
|
||||
root_logger = logging.getLogger()
|
||||
root_logger.setLevel(logging.INFO)
|
||||
|
||||
# 清除任何现有的处理程序
|
||||
for handler in root_logger.handlers[:]:
|
||||
root_logger.removeHandler(handler)
|
||||
|
||||
# 创建控制台处理程序
|
||||
console_handler = logging.StreamHandler()
|
||||
console_handler.setLevel(logging.INFO)
|
||||
console_format = logging.Formatter(
|
||||
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
console_handler.setFormatter(console_format)
|
||||
root_logger.addHandler(console_handler)
|
||||
|
||||
# 创建文件处理程序(限制每个文件大小为5MB,最多保留5个备份)
|
||||
file_handler = RotatingFileHandler(
|
||||
log_file, maxBytes=5 * 1024 * 1024, backupCount=5, encoding="utf-8" # 5 MB
|
||||
)
|
||||
file_handler.setLevel(logging.INFO)
|
||||
file_format = logging.Formatter(
|
||||
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
file_handler.setFormatter(file_format)
|
||||
root_logger.addHandler(file_handler)
|
||||
|
||||
# 记录启动信息
|
||||
logging.info("日志系统初始化完成")
|
||||
logging.info(f"日志文件: {log_file}")
|
||||
|
||||
return root_logger
|
||||
Reference in new issue
Block a user