今天课太多,一直没时间搞。下午利用一点时间进行了测试与整合,以头条发布为例。形成了通用的脚本模型及处理代码部分。目前已经能成功发布。其他平台没测试。看来得下一周再继续了,周五了。
yaml部分关于测试的部分。注意在文本方面输入有两种:一种是fill 一种是type.另外输入框获取焦点的方式,是在F12测试时,观察其如class闪动的地方,进行点击即可得到焦点。然后进行内容的type.
- name: 头条
url: https://www.toutiao.com/
cookies_path: cookies/toutiao
login_identifier: ".user-list.ttp-popup-container" # 头条登录后的用户账户链接选择器
url_pattern: https://mp.toutiao.com/profile_v4/graphic/publish # 匹配头条的文章发布页面
auto_actions:
- type: click
selector: ".close-btn" # 关闭弹窗
timeout: 10000
# - type: click
# selector: textarea[placeholder="请输入文章标题(2~30个字)"]
# timeout: 10000
- type: fill # 填充标题
selector: textarea[placeholder="请输入文章标题(2~30个字)"]
content: "我是测试标题"
options:
delay: 1000
- type: wait
timeout: 500 # 等待5秒
- type: click # 点击编辑器
selector: ".ProseMirror"
timeout: 10000
- type: type # 输入内容
selector: "span.syl-placeholder.ProseMirror-widget[ignoreel='true']"
content: "我是测试内容"
options:
delay: 1000
- type: click # 点击第三个选项
selector: "div.byte-radio-group label:nth-of-type(3)"
timeout: 500 # 等待5秒
- type: click # 点击作品声明
selector: "div.source-info-wrap label:nth-of-type(3)"
timeout: 500 # 等待5秒
- type: click # 点击预览
selector: "div.garr-footer-publish-content button:nth-of-type(1)"
timeout: 10000
- type: click # 点击发布
selector: "div.garr-footer-publish-content button:nth-of-type(3)"
timeout: 10000
关键代码,还可以扩充上传文件,视频等内容。目前因用不到所以没有进行测试。
async def perform_actions(self,page, actions):
"""执行自动化操作序列"""
for action in actions:
try:
action_type = action.get("type")
if action_type == "fill":
await self.handle_fill(page, action)
elif action_type == "click":
await self.handle_click(page, action)
elif action_type == "wait":
await self.handle_wait(action)
elif action_type == "type":
await self.handle_type(page,action)
else:
print(f"未实现的动作类型: {action_type}")
except Exception as e:
print(f"执行动作失败: {action},错误: {e}")
async def handle_click(self,page, action):
"""处理点击操作"""
selector = action["selector"]
timeout = action.get("timeout", 5000)
# 等待元素可点击
await page.wait_for_selector(selector, state="visible", timeout=timeout)
await page.click(selector)
print(f"点击元素 {selector}")
async def handle_fill(self,page, action):
"""处理填充操作"""
selector = action["selector"]
content = action["content"]
options = action.get("options", {})
# 等待元素出现
await page.wait_for_selector(selector, timeout=action.get("timeout", 5000))
# 使用 fill 方法
await page.fill(selector, content)
print(f"填充字段 {selector} 为 {content}")
# 处理 delay 选项
delay = options.get("delay", 0)
if delay:
await page.keyboard.type("", delay=delay) # 通过空输入模拟延迟
async def handle_type(self,page, action):
"""处理填充操作"""
selector = action["selector"]
content = action["content"]
options = action.get("options", {})
# 等待元素出现
await page.wait_for_selector(selector, timeout=action.get("timeout", 5000))
# 使用 fill 方法
await page.type(selector, content)
print(f"填充字段 {selector} 为 {content}")
# 处理 delay 选项
delay = options.get("delay", 0)
if delay:
await page.keyboard.type("", delay=delay) # 通过空输入模拟延迟
最关键的函数,对自动化的部分进行了修改。
async def browser_main(idx: int, auto: bool = False, headless=False):
manager = BrowserManager()
max_retries = 3
for retry in range(max_retries):
try:
if manager._context_closed:
await manager.close_all()
await manager.initialize(headless=headless)
config = ConfigManager()
page = await manager.get_page(idx,auto=auto)
if auto:
url = config.get_url_pattern(idx)
print(f"自动工作模式开启,使用URL模式:{url}")
await page.goto(url, wait_until="load")
# 新增:执行自动化操作
auto_actions = config.get_auto_actions(idx)
await manager.perform_actions(page, auto_actions) # 调用模块化函数
else:
url = config.get_site_url(idx)
login_selector = config.get_login_identifier(idx)
await page.goto(url, wait_until="load")
print(f"手动模式开始,使用URL:{url}")
print(f"当前页面索引:", list(manager._pages.keys()))
# 检测登录状态
if not auto:
logged_in = await manager.is_logged_in(page, login_selector)
return (idx, logged_in)
break
except Exception as e:
if retry < max_retries - 1:
print(f"任务执行失败,重试第 {retry + 1} 次: {e}")
manager._context_closed = True
else:
print(f"任务执行失败,已达到最大重试次数: {e}")
其他部分无修改。下一步需要进一步加工的部分在于外部文件的导入。完成后自动关闭当面page。准备给下一个任务使用。计划每次只发布一个网站,如果要一个站点多次发布的。则需要循环即可。或不关闭等待下一次的使用。但不科学,万一有上百个要发布的,会卡的。另外还需要使用小型数据库进行管理。