ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用Cursor+Playwright实现浏览器自动化:AI自动发布头条文章实战

用Cursor+Playwright实现浏览器自动化:AI自动发布头条文章实战 前几天我干了一件挺有意思的事让 AI 自己发布了一篇头条文章。具体来说就是用 Cursor 当“编程大脑”用 Playwright 当“机械手”控制一个真实的 Chrome 浏览器打开头条创作平台登录、写标题、填正文、点发布一气呵成。中途我只做了一件事——扫码登录的时候掏了一下手机。这套组合其实值得每个做测试、做运营、做内容的人关注Playwright 是当前最主流的 web 浏览器自动化框架Cursor 是能读懂整个工程上下文、直接帮你生成和修改代码的 AI 编程工具。两者配合起来相当于你有了一个能自己看页面、自己写脚本、自己修报错的“实习生”。这篇文章就把整个实战过程拆开讲清楚从为什么这样选型到环境怎么搭、脚本怎么让 Cursor 写、完整发布流程怎么落地再到我实际踩过的坑和对应解法尽量做到你能按着文章思路复刻一个自己的版本。1. 项目拆解先搞清这个自动化到底要做什么1.1 标题里藏着三个关键词很多人看到“让 AI 自动发布文章”会以为难点在“AI 写文章”但真正动起手来你会发现文章内容反而是最简单的一环瓶颈全在“浏览器操作”这一层。拆开来看这个标题里有三个关键技术点Playwright微软开源的浏览器自动化框架支持 Chromium、Firefox、WebKit。它通过一套统一的 API 去控制真实浏览器内核能模拟点击、输入、截图、读取页面内容、处理多个标签页几乎是目前做 web 端自动化测试和 RPA 类工具的首选。Cursor一款 AI 编程 IDE本质上是 VS Code 的“魔改版”核心能力是能读取你整个项目目录结合当前打开的代码文件来回答问题、成段生成代码、在指定位置修改代码。你可以把它理解成“离代码最近的那档 AI 助手”。web 浏览器操作这里不是指打开浏览器看网页而是指让程序替代人完成一系列页面上的真实操作包括登录、跳转、填写表单、点击按钮、等待反馈。这个项目的本质是让大模型通过 Cursor 帮你写出“一段控制真实浏览器的程序”然后这段程序替代人工完成“在头条创作后台上发布一篇自带标题和正文的文章”。AI 既参与了写脚本也参与了写内容。1.2 为什么第一个场景选“发布头条文章”我见过不少人拿到 Playwright 后的第一个想法是“我要写个抢票脚本”或者“我要批量注册”。这类需求在合规上天然有问题而且网站的反自动化策略往往非常激进根本不适合新手用来练手。相比之下“发布自己账号下的文章”是个边界清晰、价值明显、风险可控的场景流程固定登录 → 进入创作中心 → 新建文章 → 填标题 → 填正文 → 提交发布。整条链路每一步都明确适合写成脚本。结果可校验发布成功后页面会出现明确的成功提示或者能从文章列表里看到新记录。这对自动化脚本非常重要——有没有成功是可以用代码断言出来的。价值可见如果你是一个每天要在多个平台同步内容的创作者这玩意儿能直接省下十几分钟重复劳动比写一百个“hello world”练习都让人有动力。风险可控发布的是自己原创内容使用的是自己账号频率不高属于正常用户行为。拿它学习浏览器自动化心态上踏实很多。1.3 方案选型为什么是 Playwright Cursor而不是其他组合也许你会问做浏览器自动化不是还有很多工具吗像 Selenium、Puppeteer、Pyppeteer为什么偏偏选 Playwright而写脚本为什么不纯手写非得拉上 Cursor先对比 Selenium。Selenium 确实老牌但它的底层是 WebDriver 协议和浏览器通信要经过一个中间服务很多版本在元素定位、页面等待、多标签处理上的体验都比较“古老”。Playwright 走的是 Chrome DevTools Protocol 这一条更贴近浏览器内核的通道最让我受用的三点是自动等待做得很好。Playwright 的大多数操作会内置等待机制比如点击元素之前会等它稳定、可见、可被点击而不是像 Selenium 那样没等到就报错。上下文和登录态管理方便。一个BrowserContext相当于一个独立的浏览器会话天然隔离 Cookie、缓存还能一键保存和恢复登录状态。自带 codegen 录制器。可以直接录一段人工操作生成基础代码省掉最反人类的“手动查选择器”环节。再说不纯手写的问题。手写一个发布脚本的技术难度确实不高但真正耗时间的地方在于你得反复打开开发者工具看 DOM、试各种选择器、处理页面加载慢、判断“到底执行到哪一步了”。这些恰恰是 Cursor 这类 AI 工具擅长的——你只要给它一个明确的页面目标和你录出来的代码片段它能很快整理出可用的主流程。人负责判断方向和最终把关AI 负责快速生成和调错这套分工我实测下来效率非常高。也有人问“为什么不直接用现成的 RPA 工具” 因为现成工具通常绑定特定平台只能选择已有的动作组件灵活性不足。用 Playwright 写本质上是在写一套完全属于自己的“浏览器遥控器”换一个网站、换一种操作改代码就行。2. 环境准备让 Playwright 在本地跑起来的完整过程2.1 用 Python 还是 Node.jsPlaywright 官方提供 JavaScript/TypeScript 和 Python 两套主要 SDK另外也有 Java 和 .NET。我自己选的是 Python理由很朴素我后续想把发布结果写进 Excel 做记录还想接一些数据分析和 AI 相关的库Python 这边生态最顺。如果你本身就是前端开发者用 TypeScript 也完全没问题核心 API 的设计是一致的。安装 Python 版本只需要两步pip install playwright playwright install chromium第一条命令装的是核心库第二条命令是下载浏览器内核。默认会下载 Chromium 三个发行渠道中的统一版本实际跑的时候用p.chromium.launch()就能拉起它。如果你用 Node 生态对应的命令是npm init -y npm i -D playwright npx playwright install chromium这里有个非常容易踩的坑playwright install下载浏览器依赖的是国外的 CDN在国内网络环境下经常下到一半卡死或者报ETIMEDOUT。解决办法是用国内镜像比如设置环境变量指向 npmmirror 的浏览器下载地址# Windows PowerShell $env:PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright playwright install chromium # macOS / Linux export PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright playwright install chromium如果你是在 Linux 服务器上跑还需要装一批系统依赖库最好直接用官方参数装playwright install --with-deps chromium不然大概率会遇到启动浏览器时缺.so动态库的报错这类报错信息往往很吓人其实只是系统依赖没装齐。2.2 第一个脚本先让浏览器自己打开环境装好之后我建议你先不要急着写业务代码花两分钟写一个最小脚本验证整条链路通不通from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch(headlessFalse) page browser.new_page() page.goto(https://mp.toutiao.com) page.wait_for_timeout(3000) browser.close()这里有两个细节值得说。第一headlessFalse表示有头模式也就是你会肉眼看到一个 Chrome 窗口打开并自动跳转。第一次跑自动化务必用有头模式因为你得确认浏览器真的启动了、页面真的加载了。等到脚本稳定之后再改成headlessTrue做无人值守。第二page.wait_for_timeout(3000)只是我用来“肉眼观察”的临时等待不是常规手段。正式代码里不要频繁用这种固定sleep优先用条件等待也就是等待某个元素出现或某个操作完成。关于这一点后面第五节会展开讲。2.3 录制脚本用 codegen 先把人工操作变成代码Playwright 最让我上头的功能就是录制定向叫codegen。它相当于一个“浏览器录像机”你正常在浏览器里操作它在一旁把每一步翻译成代码输出。启动命令是python -m playwright codegen https://mp.toutiao.com如果是 Node 项目npx playwright codegen https://mp.toutiao.com启动后你会看到两个窗口一个是真实浏览器一个是实时同步生成的代码面板。这时候你就手动走一遍发布文章的全流程登录、进创作中心、点发布文章、编辑器的位置先点一下再随便写几个字、把标题框也点一下。等到操作结束后你已经拿到了一份能跑通基础路径的脚本。但这里必须提醒一句codegen 生成的代码质量比较“粗糙”。它的优势是选择器抓得准因为那些选择器是它从真实页面 DOM 里录出来的缺点是逻辑完全是直铺的没有函数封装没有异常处理没有登录态复用很多时候还夹着一大堆wait_for_timeout。我的习惯是把 codegen 当成“翻译工具”生成完代码后直接丢给 Cursor 做结构化重构而不是当成最终答案。3. 用 Cursor 生成自动化脚本提示词与分层设计3.1 Cursor 能做什么、不能做什么Cursor 的强项是能理解你的项目上下文也就是说它不像网页版 ChatGPT 那样只能看到聊天框里的内容而是能直接读你当前工作区里的文件、记住你的目录结构、在指定文件里插入或修改代码。写 Playwright 脚本这种任务天然适合它你需要反复根据真实页面的 DOM 结构生成定位代码而这些结构信息可以通过你的描述、报错信息、甚至完整的 HTML 片段喂给它。但它也不是万能的。最重要的一点是它没有“亲眼”看过你的页面也不会替你跑代码。所以你不能只丢一句“帮我写个自动发布头条文章的脚本”然后指望一次成功。你得给它足够的信息用哪个框架、目标页面地址、操作顺序、登录方式、内容从哪里来、发布成功的标志是什么。另外要提醒一个很多人忽略的点Cursor 本质是云端的模型服务对话内容会被发送给模型提供商。所以不要把各种密钥、Token、Cookie、账号密码直接粘进对话里。脚本要用的密钥放本地环境变量或.env文件让代码去读取即可。这个习惯要从第一天就养成。3.2 把需求讲清楚一段可复用的提示词结构我实际操作下来最顺手的提示词组织方式是“背景 原料 目标 限制”。下面是我这次用的一段提示词的结构你可以直接套“我准备用 PlaywrightPython 版写一个自动发布文章到头条创作平台的脚本。当前页面入口是 https://mp.toutiao.com登录后进入创作者后台。我已经用 codegen 录了一段基础操作代码贴在下面……粘贴录制代码。请把这段代码重构为清晰的分层结构config.py 存 URL 和路径publisher.py 写核心发布流程main.py 负责串联。要求1所有定位器都带超时时间2标题和正文从本地 article.md 读取3发布前点击发布按钮后等待“发布成功”的提示出现再返回4发布完成后截图保存到当前目录。代码先解释你的设计再给完整文件。”这里面的“目标”和“限制”尤其重要。你如果不告诉它要等“发布成功提示”它很可能就只会机械地“点完发布就结束”那脚本等于没有结果校验。你如果不告诉它“标题从本地文章读取”它就默认写死一条示例内容后面你每次发布都得改代码。3.3 生成代码的分层设计经过 Cursor 重构后我的工程目录长这样auto-publish/ ├── config.py # 全局配置URL、超时时间、文件路径 ├── login.py # 首次登录保存登录态到 state.json ├── publisher.py # 核心发布流程读取文章、填写、发布 ├── main.py # 入口加载登录态调用 publisher ├── article.md # 待发布的文章标题正文 ├── state.json # 登录态文件首次登录后自动生成 └── requirements.txt为什么要分层因为你不分层的话登录逻辑、页面逻辑、内容读取逻辑全搅在一个文件里后续改任何一处都要在大几百行的代码里找。分层之后的好处很直接如果某天头条后台的“发布按钮”选择器变了我只需要改publisher.py根本碰不到登录逻辑和内容读取逻辑。publisher.py的核心骨架大概是这样的from playwright.sync_api import Page, expect class ArticlePublisher: def __init__(self, page: Page, config: dict): self.page page self.config config def go_to_editor(self): # 进入创作中心后打开新建文章页面 self.page.goto(self.config[editor_url]) self.page.wait_for_load_state(networkidle) def fill_title(self, title: str): title_input self.page.locator( input[placeholder*请输入标题] ) expect(title_input).to_be_visible(timeout10_000) title_input.fill(title) def fill_content(self, content: str): editor self.page.locator(.ProseMirror) editor.click() self.page.keyboard.insert_text(content) def publish(self): publish_btn self.page.get_by_role(button, name发布) publish_btn.click() success self.page.locator(text发布成功) expect(success).to_be_visible(timeout30_000)注意这里我用的选择器是.ProseMirror这只是我这次录制到的编辑器 class不同时期头条后台的 DOM 可能不一样。凡是页面结构相关的地方都应该以你自己codegen录制出来的为准。这也是为什么第一步一定是“录一遍再重构”凭空很难猜出真实的 DOM。3.4 第一次跑通后必须补齐的“经验型代码”Cursor 第一次生成的代码能跑通主流程但离“可放心使用”还差三块很重要的东西我第一次跑的时候没加结果翻车了。这三块分别是登录态复用。自动化脚本每次启动都重新扫码登录很折腾而且头条的扫码登录二维码有时效流程可能因为等你扫码而中断。正确做法是第一次手动登录后把BrowserContext里的登录状态保存成文件后续脚本直接加载。代码就两行# 首次登录时保存 page.context.storage_state(pathstate.json) # 后续启动时复用 context browser.new_context(storage_statestate.json)幂等控制。自动化脚本最怕重复执行。如果发布按钮点了一次但页面响应比较慢你可能以为失败了又跑一次结果就发了两篇一模一样的文章。我的解决方式是在publisher.publish()之前检查从本地的published.jsonl文件读取历史发布记录如果article.md的第一行标题已经在记录里就直接中止发布。失败现场留证。页面操作不可能永远不出问题出问题的时候你得知道当时发生了什么。我的做法是在任何异常分支里都加一行截图try: publish_btn.click() except Exception: page.screenshot(pathferror_{timestamp}.png) raise不要小看这三块它们决定了一个自动化脚本是“能跑”还是“能长期用”。4. 完整发布流程实现登录、填内容、点发布的代码细节4.1 登录后保持会话storageState 的正确玩法先聊登录。头条的创作者后台登录方式主要是扫码偶尔有手机验证码。自动化脚本直接走验证码会非常麻烦因为收码环节绕不开手机验证。所以我最终采用的是“人工登录一次 保存登录态”的方案这是目前最稳、也最合规的做法第一步用一个有头模式的脚本打开登录页人工扫码等页面跳转进创作者后台后执行from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch(headlessFalse) context browser.new_context() page context.new_page() page.goto(https://mp.toutiao.com) input(扫码登录完成后按回车继续...) context.storage_state(pathstate.json) browser.close()第二步之后所有自动化脚本都这样加载登录态context browser.new_context(storage_statestate.json) page context.new_page() page.goto(https://mp.toutiao.com)这里有个很容易忽略的坑storage_state里存的是 Cookie 和本地存储但很多平台的后台会校验 User-Agent 和浏览器环境指纹。如果你第一次保存登录态用的是有头模式后面加载时却用了完全不同的浏览器启动参数登录态有可能失效。所以我建议正式使用后所有脚本尽量保持一致的浏览器启动参数不要今天有头明天无头混着来。4.2 页面元素定位创作平台的关键节点头条创作平台的页面结构在不同的登录态、不同时间点会有差别但大体上是固定的几个步骤进入创作中心 → 左侧“发布”菜单 → 选择“文章” → 进入文章编辑页。文章编辑页最关键的两个元素是标题输入框和正文编辑器。标题输入框通常是input我用的是 placeholder 模糊匹配title_input page.locator(input[placeholder*请输入标题]) title_input.fill(title)注意这里用fill而不是press_sequentially因为fill会一次性设置值速度极快且稳定。press_sequentially是为了模拟真人逐字输入但它在富文本场景容易因为焦点问题漏字符能不用就不用。正文编辑器要麻烦一点。它往往是contenteditable的 div而不是传统的textarea。对于 Playwright 而言fill()方法对 contenteditable 的支持时好时坏具体取决于页面的实现方式。我这次遇到的情况是必须点击编辑器、获得焦点然后通过keyboard.insert_text()模拟输入editor page.locator(.ProseMirror) editor.click() page.keyboard.insert_text(body_text)这里还有一个小知识点keyboard.insert_text()插入中文没有问题但如果正文里包含很多换行和特殊字符建议先进行一次格式预处理把 Markdown 的#、**等符号转成目标平台能理解的纯文本或 HTML。头条的富文本编辑器支持一定程度的粘贴排版如果直接插入带 Markdown 符号的原文发布出去的文章可读性会很差。4.3 文章内容从哪里来AI 生成与数据文件很多人听说“AI 自动发布文章”下意识会想“是不是让 AI 现场写一篇然后直接发”。技术上确实可以做但我更推荐“内容准备与发布执行分离”的方案发布动作由 Playwright 完成而文章内容平时已经准备好存在本地article.md里。这样做有个巨大的好处——你可以在发布前人工检查文章内容和格式而不是把一个 AI 临时生成的偏偏文本直接丢给平台。内容生成这一步我用的是 Cursor。具体做法是在 Cursor 的对话里给定一个写作主题和字数要求让它先写一版草稿我再手动改一遍确认没毛病保存成article.md。脚本读取这个文件的逻辑很简单import re with open(article.md, r, encodingutf-8) as f: lines f.read().strip().split(\n) title lines[0].lstrip(# ).strip() body_text \n.join(lines[1:]).strip()当然如果你就是想全自动也可以让 Cursor 帮你写一段调用大模型 API 生成文章的代码。大致思路是把主题写入一个topic.txt脚本启动后请求大模型接口拿到文章内容再直接填入页面。但我要泼一盆冷水——内容质量是自动化的上限而不是代码本身的功劳。平台不缺文章缺的是至少对读者负责的内容。自动化帮你节省的是操作时间不是思考时间。4.4 发布动作和结果校验点完按钮之后怎么办发布按钮在整个流程里是最需要谨慎处理的位置。我遇到的页面结构里右上角有个“发布”按钮点击后会再弹出一个确认框或下拉菜单需要再次点击“发布”才算最终提交。完整发布动作建议写成这样def publish_article(page): publish_btn page.get_by_role(button, name发布).first publish_btn.click() # 有些情况下会弹出二次确认尝试处理但不强制 confirm_btn page.get_by_role(button, name发布确认提交).first try: confirm_btn.click(timeout3_000) except Exception: pass # 等待成功提示出现 success page.locator(text发布成功) expect(success).to_be_visible(timeout30_000)用get_by_role(button, name发布)来定位按钮是我特别推荐的做法。它基于无障碍语义来查找元素通常比直接抄 class 名稳定得多。哪怕按钮的长相换了、class 版本换了只要还是同一个按钮名字没变就能找到。expect(...).to_be_visible(timeout30_000)则是官方推荐的等待方式它的含义是“在 30 秒内这个元素必须是可见的才通过”。如果发布没有成功这里就会抛超时异常。加上我前面提到的截图逻辑跑挂了也能看清现场。4.5 安全边界频率、合规与人工兜底把发布自动化跑通之后有两件事我特别想强调因为它们比技术更影响你长期使用这套东西的安稳程度。第一合规边界。自动化脚本能做的事很多但“能不能做”和“该不该做”是两码事。我这次的做法是只发布自己账号下的原创内容不搞批量注册小号不刷阅读、不刷评论、不买量也不去试图绕过平台的风控和验证机制。这类事情轻则封号重则给自己惹上一堆不必要的麻烦完全不值得。第二频率控制。哪怕只是正常发布也不要一下子上线一个“每分钟发一篇”的脚本。平台对非常规频率是有感知的。我自己会在关键操作之间加一些随机间隔把这个也写进了流程里import random import time time.sleep(random.uniform(2, 5))间隔别写死随机一点更像真人操作也更不容易触发无谓的风控提醒。自动化追求的是高效但没必要高到“看起来不像人”。第三人工兜底。我最后的发布会做成半自动模式脚本把标题和正文填好之后会先弹出一个确认提示等人工看一眼草稿再决定是否真正点发布。这种“半自动”的模式听着比“全自动”笨实际上是我最推荐的姿势。因为文章一旦发出去了撤回一文成本可不算低。5. 我踩过的坑Playwright Cursor 常见问题排查5.1 浏览器下载失败与安装报错这几乎是每个新手都会遇到的第一道坎。我在 2.1 节已经提到了镜像环境变量这里补充一个更容易被忽略的情况有时候playwright install显示下载成功但运行时仍然报错找不到浏览器可执行文件。原因通常是版本不一致——你pip install的 Playwright 版本和之前playwright install下载浏览器时的版本不是同一套。解决办法是每次升级库版本后都要重新执行一次安装pip install -U playwright playwright install chromium或者干脆在项目里锁定版本pip install playwright1.44.0千万不要用“最新版安装失败就降级再装”这种思路反复折腾。先敲playwright --version查看版本再对照官方文档确认浏览器版本要求比瞎试靠谱得多。5.2 选择器不稳定今天能跑明天报错页面自动化最大的敌人就是 DOM 变化。今天还能定位到的选择器明天后台前端一改版就失效了。这是 Playwright 项目维护中无法完全避免的问题只能尽量降低影响。我总结了几个让选择器更抗造的技巧优先用get_by_role或get_by_text它们基于元素的语义和可见文本而不是一串可能随时变化的 class。不要复制一长串div div div路径。这种绝对路径是最脆的页面层级稍微一变就全崩。对会变的 ID/class 做模糊匹配比如locator([class*editor])少用精确匹配。顺手给关键页面元素加注释标明“这个元素是标题输入框”下次选择器失效时你能快速知道要修哪里。选择器崩了不要慌先用 codegen 重新录一遍拿到新的选择器再对比旧代码找出变化点。这比对着浏览器按 F12 瞎猜效率高多了。5.3 验证码、登录风控与合规处理自动化登录时平台会弹出验证码或要求滑块验证。很多教程会教你用第三方打码平台或者模拟拖拽但我要明确说这类“绕过风控”的操作我不建议做也不展开讲。原因很简单验证码本身是平台安全策略的一部分尝试绕过它既违反平台规则也容易把自己的账号搭进去。我的处理方式就是前面说的第一次登录人工完成把登录态保存下来后续脚本只在会话有效期内执行。如果哪一天脚本跑起来发现登录失效了那就停下来重新跑一次“人工扫码登录”的流程再继续。这中间损失的不过是几十秒换来的是账号安全和心理安稳。注意凡是脚本里涉及登录态失效的情况不要偷偷摸摸自动重试太多次。设置一个失败中止逻辑提示人工介入反而更省心。5.4 跑一半卡住超时和等待策略这是自动化脚本最常见的一种“死法”页面加载很慢脚本等不到目标元素卡在一个wait_for上直到超时报错。排查思路是分层的先看报错超时的元素是哪个它到底“是否出现过”但“不稳定”还是“完全没出现”。用截图确认脚本卡住时页面长什么样。很多时候你会发现页面弹了一个“是否确认离开”的浏览器原生对话框或者有个遮罩层挡住了按钮脚本是点击到了遮罩层上。然后用page.pause()一键进入调试模式。Playwright 支持在代码里插一行page.pause()运行到这里的时候脚本会暂停并打开 Playwright Inspector你可以在这时候手动操作浏览器、断点续跑效果比传统print调试好很多。关于等待我的一条经验是尽量用操作自带的等待而不是手动写长超时。比如点击按钮前它自己会等元素可点填写前可以用expect(...).to_be_visible确保元素真的渲染出来了。真正的网络请求等待才需要page.wait_for_load_state(networkidle)。固定sleep是最后手段能不用就不用。5.5 Cursor 生成的代码报错问题出在哪Cursor 生成 Playwright 代码的报错大多数时候不是 Playwright 的问题而是信息不足。我遇到过的典型案例它假设了一个不存在的editor_url结果goto到一个错误页面。它使用了fill()填充 contenteditable 编辑器但运行时无声失败。它生成的等待条件太严苛等待某个只在有头模式才出现的元素导致无头运行必挂。处理思路很明确不要急着让 Cursor 盲修先自己从报错信息里定位是“定位、等待、还是流程”哪一类问题然后再贴足够的信息给它。我推荐的提问格式是“下面这行代码报错了…… 完整报错信息是…… 当前页面的相关 HTML 片段是…… 请帮我判断是选择器问题还是等待问题并给出修改后的代码。”把报错和现场信息喂进去之后Cursor 的有效率会显著提升。它偶尔会过度自信地给出一个看似合理但实际跑不通的方案这种时候别信口开河直接拿代码去跑一遍验证。和 AI 协作的正确姿势是把它当“手速很快但对环境半生不熟的同事”而不是“全知全能的神”。6. 后续还能怎么玩扩展方向与我的体会6.1 扩展方向多平台分发、定时发布、数据回传这套“Playwright Cursor”的组合能力边界非常大发布头条文章只是起点。顺着同样的技术栈你可以做非常多的事情多平台分发。把publisher.py抽象成接口每个平台写一个实现类比如ToutiaoPublisher、WeixinPublisher、ZhihuPublisher。配置文件里存各平台的登录态和编辑页 URL一份内容发布到 N 个平台。定时发布。如果脚本运行环境是 Linux 服务器配合 cron 就能实现在指定时间自动执行发布任务。Windows 上也可以用计划任务。但记住前面说的频率别太夸张。数据回传。发布完不等于结束你完全可以让 Playwright 再回到文章列表页抓取初始阅读量、评论数写进一个 CSV 或数据库长期积累自己内容的数据曲线。作为 UI 回归测试。如果你在一个内容团队工作发布流程本身就是一个典型的高频操作流程完全可以把它组织成 Playwright Test 用例每次后台改版后跑一遍验证主流程没有回归。在测试工程化的语境下这套东西的价值就更直接了。Playwright 本身就是为了测试而生的codegen 录制的操作、expect断言的模式、page.screenshot的现场留存都是标准的测试方法论。与其把它当成一次性的自动发布脚本不如当成一个可以长期沉淀的“UI 自动化测试资产”。6.2 我的体会全自动不如可控的半自动最后说一句个人体会。这套项目做完之后我最大的收获反而不是“省了几分钟发布文章的时间”而是形成了一种思维任何重复的网页操作都能被脚本化。看到一个新的后台系统我第一反应是“它的操作路径是什么、状态返回值是什么、哪些环节能被自动化”而不是“这个太复杂了不搞了”。但同时我也越来越确定所谓的“全自动”往往是伪命题。真正常态的自动化流程里总有那么几个节点需要人工介入比如登录扫码、内容审核、异常处理。把这些节点识别出来把自动化用在重复度最高、出错影响最小的环节才是最舒服、最长久的使用姿势。Cursor 在这个流程里的角色是一个能快速把你的想法变成代码、又能基于报错迭代修改的协作者。Playwright 的角色则是一双对网页操作极度精准的手。两者结合真正替代掉的不是“思考”而是“重复”。我建议你也找一个自己工作中最烦、最重复的网页操作练练手别贪多就从“回车就能发布一篇文章”这种小事开始。跑通的那一瞬间那种“浏览器自己动起来了”的感觉确实挺上头的。
返回列表