2026/1/28 2:42:32
网站建设
项目流程
国家小城镇建设政策网站,网站建设哪家好 上海,网站程序制作,中国建筑网官网手机版前言:为什么我要折腾这个
最近在做SEO优化,发现手动去各个平台发外链真的太累了。Reddit发一圈、Quora答几个问题、各种论坛注册发帖… 一天下来手都要废了。
作为一个会写代码的独立开发者,我就想:这种重复劳动,为什么不让机器来做呢?
于是就有了这篇文章。今天教大家用Pl…前言:为什么我要折腾这个最近在做SEO优化,发现手动去各个平台发外链真的太累了。Reddit发一圈、Quora答几个问题、各种论坛注册发帖… 一天下来手都要废了。作为一个会写代码的独立开发者,我就想:这种重复劳动,为什么不让机器来做呢?于是就有了这篇文章。今天教大家用Playwright来实现自动发外链。为什么选Playwright而不是Selenium?说实话,我之前一直用Selenium,但后来发现Playwright真的香:速度更快- 启动浏览器、执行操作都比Selenium快API更现代- async/await支持,代码写起来舒服更稳定- 自动等待机制做得很好,不用到处写sleep多浏览器支持- Chromium、Firefox、WebKit都能用最关键的是,文档写得清楚,遇到问题Google一下基本都能解决。环境准备首先装一下Playwright。我用的是Python,因为写起来快:pipinstallplaywright playwrightinstallchromium这个playwright install chromium会下载浏览器,第一次可能要等一会儿,喝杯咖啡就好了。第一个例子:自动登录Reddit我们先从简单的开始,实现自动登录Reddit。fromplaywright.sync_apiimportsync_playwrightimporttimedeflogin_reddit(username,password):withsync_playwright()asp:# 启动浏览器,headlessFalse可以看到浏览器操作browserp.chromium.launch(headlessFalse)pagebrowser.new_page()# 打开Reddit登录页page.goto(https://www.reddit.com/login/)# 等待页面加载page.wait_for_load_state(networkidle)# 填写用户名page.fill(input[nameusername],username)# 填写密码page.fill(input[namepassword],password)# 点击登录按钮page.click(button[typesubmit])# 等待登录完成time.sleep(3)print(登录成功!)# 保持浏览器打开,方便调试input(按回车关闭浏览器...)browser.close()# 使用示例login_reddit(your_username,your_password)几个要注意的点:headlessFalse- 开发的时候一定要设成False,能看到浏览器在干什么,方便调试wait_for_load_state- 等待页面加载完成,不然可能找不到元素选择器 -input[nameusername]这种CSS选择器,用浏览器的开发者工具很容易找到进阶:自动发帖到Reddit登录搞定了,接下来发帖:defpost_to_reddit(username,password,subreddit,title,content,link):withsync_playwright()asp:browserp.chromium.launch(headlessFalse)contextbrowser.new_context()pagecontext.new_page()# 先登录page.goto(https://www.reddit.com/login/)page.wait_for_load_state(networkidle)page.fill(input[nameusername],username)page.fill(input[namepassword],password)page.click(button[typesubmit])# 等待登录完成page.wait_for_url(https://www.reddit.com/,timeout10000)print(登录成功)# 去到指定的subredditpage.goto(fhttps://www.reddit.com/r/{subreddit}/submit)page.wait_for_load_state(networkidle)# 选择发帖类型(Link)page.click(button[data-namelink])time.sleep(1)# 填写标题page.fill(textarea[nametitle],title)# 填写链接page.fill(input[nameurl],link)# 填写内容(如果有)ifcontent:page.fill(div[contenteditabletrue],content)# 点击发布page.click(button:has-text(Post))# 等待发布完成time.sleep(3)print(发帖成功!)input(按回车关闭...)browser.close()# 使用示例post_to_reddit(usernameyour_username,passwordyour_password,subredditwebdev,titleCheck out my new tool!,contentI built this cool thing...,linkhttps://yoursite.com)实战技巧:处理各种坑1. 反爬虫检测很多网站会检测你是不是机器人。几个应对方法:# 使用真实的User-Agentcontextbrowser.new_context(user_agentMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36)# 随机延迟importrandom time.sleep(random.uniform(2,5))# 模拟人类行为:滚动页面page.evaluate(window.scrollBy(0, 300))time.sleep(1)page.evaluate(window.scrollBy(0, 300))2. 保存登录状态每次都登录太慢了,可以保存cookies:# 登录后保存cookiescontext.storage_state(pathreddit_auth.json)# 下次直接加载contextbrowser.new_context(storage_statereddit_auth.json)3. 处理验证码这个是最麻烦的。我的做法:# 检测是否出现验证码ifpage.locator(iframe[title*recaptcha]).count()0:print(检测到验证码,请手动完成)input(完成后按回车继续...)就是让程序暂停,我手动点一下验证码,然后继续。虽然不够自动化,但对于小规模使用够了。4. 错误处理一定要加try-except,不然跑到一半挂了很烦:try:page.click(button[typesubmit],timeout5000)exceptExceptionase:print(f点击失败:{e})page.screenshot(patherror.png)# 截图保存现场raise完整的外链发布脚本把上面的东西整合一下,做一个能批量发外链的脚本:fromplaywright.sync_apiimportsync_playwrightimporttimeimportrandomimportjsonclassLinkPoster:def__init__(self,headlessFalse):self.headlessheadless self.browserNoneself.contextNonedefstart(self):启动浏览器self.playwrightsync_playwright().start()self.browserself.playwright.chromium.launch(headlessself.headless)self.contextself.browser.new_context(user_agentMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36)defclose(self):关闭浏览器ifself.browser:self.browser.close()ifself.playwright:self.playwright.stop()defrandom_delay(self,min_sec2,max_sec5):随机延迟,模拟人类操作time.sleep(random.uniform(min_sec,max_sec))deflogin_reddit(self,username,password):登录Redditpageself.context.new_page()try:page.goto(https://www.reddit.com/login/)page.wait_for_load_state(networkidle)page.fill(input[nameusername],username)self.random_delay(1,2)page.fill(input[namepassword],password)self.random_delay(1,2)page.click(button[typesubmit])page.wait_for_url(https://www.reddit.com/,timeout10000)# 保存登录状态self.context.storage_state(pathreddit_auth.json)print(✓ Reddit登录成功)page.close()returnTrueexceptExceptionase:print(f✗ Reddit登录失败:{e})page.screenshot(pathreddit_login_error.png)page.close()returnFalsedefpost_reddit(self,subreddit,title,link,comment):在Reddit发帖pageself.context.new_page()try:# 去发帖页面page.goto(fhttps://www.reddit.com/r/{subreddit}/submit)page.wait_for_load_state(networkidle)self.random_delay()# 选择Link类型page.click(button[data-namelink])self.random_delay(1,2)# 填写内容page.fill(textarea[nametitle],title)self.random_delay(1,2)page.fill(input[nameurl],link)self.random_delay(1,2)ifcomment:page.fill(div[contenteditabletrue],comment)self.random_delay(1,2)# 发布page.click(button:has-text(Post))self.random_delay(3,5)print(f✓ 成功发布到 r/{subreddit})page.close()returnTrueexceptExceptionase:print(f✗ 发布到 r/{subreddit}失败:{e})page.screenshot(pathfreddit_post_error_{subreddit}.png)page.close()returnFalsedefbatch_post(self,posts_config):批量发帖success_count0fail_count0fori,postinenumerate(posts_config,1):print(f\n[{i}/{len(posts_config)}] 正在发布...)ifself.post_reddit(subredditpost[subreddit],titlepost[title],linkpost[link],commentpost.get(comment,)):success_count1else:fail_count1# 每次发帖后随机等待,避免被限制ifilen(posts_config):wait_timerandom.uniform(30,60)print(f等待{wait_time:.1f}秒后继续...)time.sleep(wait_time)print(f\n完成! 成功:{success_count}, 失败:{fail_count})# 使用示例if__name____main__:# 配置要发布的内容posts[{subreddit:SideProject,title:Built a tool to automate my workflow,link:https://yoursite.com,comment:Hey everyone, I built this tool to solve...},{subreddit:webdev,title:New dev tool for productivity,link:https://yoursite.com,comment:As a solo developer, I found...}]# 创建发布器posterLinkPoster(headlessFalse)poster.start()try:# 先登录poster.login_reddit(your_username,your_password)# 批量发帖poster.batch_post(posts)finally:poster.close()一些使用建议1. 不要太频繁每个平台都有发帖频率限制。Reddit一般建议:新账号:每天1-2个帖子老账号:每小时不超过1个不同subreddit之间间隔30分钟以上2. 内容要有价值自动化只是工具,内容质量才是关键。不要发垃圾信息,会被封号的。3. 多账号轮换准备几个账号轮流用,不要一个账号发太多。可以这样改代码:accounts[{username:account1,password:pass1},{username:account2,password:pass2},]foraccountinaccounts:poster.login_reddit(account[username],account[password])# 发一部分帖子poster.batch_post(posts[:2])time.sleep(3600)# 换账号前等1小时4. 记录日志加个日志功能,方便追踪:importlogging logging.basicConfig(filenamelink_posting.log,levellogging.INFO,format%(asctime)s - %(message)s)# 在发帖成功后logging.info(f成功发布到 r/{subreddit}:{title})其他平台怎么办?同样的思路可以用到其他平台:Quora:# 找到回答问题按钮page.click(button:has-text(Answer))# 填写答案page.fill(div[contenteditabletrue],your_answer)Medium:# 点击Writepage.click(a[href/new-story])# 填写标题和内容page.fill(h1[data-default-textTitle],title)page.fill(p[data-default-textTell your story...],content)HackerNews:# 提交链接page.goto(https://news.ycombinator.com/submit)page.fill(input[nametitle],title)page.fill(input[nameurl],url)page.click(input[typesubmit])核心就是:打开开发者工具找到对应的输入框和按钮用Playwright模拟操作最后的碎碎念这个工具我自己用了一段时间,确实省了不少时间。但说实话,最重要的还是:内容质量- 垃圾内容发再多也没用适度使用- 不要滥用,容易被封持续优化- 根据效果调整策略自动化只是让你有更多时间去做更重要的事情,比如优化产品、写更好的内容。