手搓全自动文章多平台发布系统:8、自动化脚本的测试。

今天课太多,一直没时间搞。下午利用一点时间进行了测试与整合,以头条发布为例。形成了通用的脚本模型及处理代码部分。目前已经能成功发布。其他平台没测试。看来得下一周再继续了,周五了。

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。准备给下一个任务使用。计划每次只发布一个网站,如果要一个站点多次发布的。则需要循环即可。或不关闭等待下一次的使用。但不科学,万一有上百个要发布的,会卡的。另外还需要使用小型数据库进行管理。

相关推荐
ulias2123 小时前
Linux系统中的权限问题
linux·运维·服务器
沃尔威武4 小时前
数据库 Sinks(.net8)
数据库·.net·webview
青花瓷4 小时前
Ubuntu下OpenClaw的安装(豆包火山API版)
运维·服务器·ubuntu
问简4 小时前
docker 镜像相关
运维·docker·容器
Dreamboat¿5 小时前
SQL 注入漏洞
数据库·sql
Dream of maid5 小时前
Linux(下)
linux·运维·服务器
齐鲁大虾5 小时前
统信系统UOS常用命令集
linux·运维·服务器
Benszen6 小时前
Docker容器化技术实战指南
运维·docker·容器
ZzzZZzzzZZZzzzz…6 小时前
Nginx 平滑升级:从 1.26.3 到 1.28.0,用户无感知
linux·运维·nginx·平滑升级·nginx1.26.3·nginx1.28.0
曹牧6 小时前
Oracle数据库中,将JSON字符串转换为多行数据
数据库·oracle·json