云计算百科
云计算领域专业知识百科平台

爬虫被 React 反爬拦死?知乎 Draft.js 编辑器的完整破解过程(附代码)

做自动化发布的时候,知乎是我卡得最久的一个平台——不是登录、不是风控,而是编辑器本身把我拦死了。

需求很简单:把 Markdown 文章自动发到知乎。结果内容怎么都进不去编辑器,提交一按,正文是空的。前前后后折腾了三个小时,最后发现根子在 React 上。整个过程记下来,给后来的人省点时间。

现象:内容塞进去了,一提交就丢

一开始我图省事,直接改 DOM:

const el = document.querySelector('.DraftEditor-root .public-DraftEditor-content');
el.innerHTML = contentHtml;

页面上看着明明显示出来了,一点「发布」,正文却是空的,或者只剩旧内容。你甚至能肉眼看到文字一闪,然后没了。

根因:Draft.js 是 React 受控组件,它不认你的 DOM

知乎的编辑器底层是 Draft.js,这是 React 官方出的富文本框架。它内部维护着一份自己的 state(编辑状态),页面上的文字是从这份 state 渲染出来的。

这意味着:你直接改 innerHTML,改的是浏览器里渲染出来的结果,但 React 那份 state 压根没变。等你触发提交,React 用自己 state 重新渲染,你塞进去的东西就全被「抹」回去了。

打个比方:你以为改了账本,其实你只是拿笔在账本的复印件上写了字,原件一个字没动。

破解关键:别走 DOM,走「事件」

React 不认直接赋值,但认合成事件。它监听的是浏览器的输入事件,而不是 DOM 的变化。所以正确的做法是:模拟一次真实的键盘输入,让 React 自己把这笔输入记进 state。

// 先让编辑器获得焦点(点击一下)
await page.click('.DraftEditor-root');

// 用 insertText 模拟键盘输入,触发 React 合成事件
await page.keyboard.insertText(content);

就这一句 insertText(),把 innerHTML 换成它,内容就进去了,提交也不丢了。

完整可跑通的代码

下面是发布知乎文章的完整片段(Playwright + Python):

from playwright.sync_api import sync_playwright

def publish_zhihu(title: str, content: str):
with sync_playwright() as p:
browser = p.chromium.launch(headless=False) # 知乎反爬,建议 headful
page = browser.new_page()
page.goto("https://zhuanlan.zhihu.com/write")

# 填标题
page.fill('.WriteIndex-titleInput', title)

# 填正文:先点编辑器获得焦点,再模拟键盘输入
page.click('.DraftEditor-root')
page.keyboard.insert_text(content)

# 点发布
page.click('button:has-text("发布")')
browser.close()

几个关键点:

  • headless=False——知乎对无头浏览器检测很严,用有头模式成功率高得多。
  • insert_text() 是核心,fill() 对 React 受控组件经常失效。
  • 别用固定 sleep,等「发布成功」的状态元素出现再结束,比瞎等可靠。
  • 这套思路通用

    凡是「你改了 DOM 但页面不认」的场景,基本都是 React / Vue 这类框架的受控组件在作怪。记住一条:框架维护状态的场景,一律走事件,不走赋值。 知乎是 Draft.js,其他平台也有各自的富文本框架,思路都一样。


    做数据采集、自动化脚本、多平台发布的朋友,如果你也被某个平台的反爬卡住了,欢迎来找我聊聊。

    接单范围:Python 脚本定制、数据采集(含反爬破解)、自动化代做、多平台自动发布。闲鱼直接搜「反爬 数据采集」就能找到我,或者 CSDN 站内私信,说明你的需求,我看到了就回。


    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 爬虫被 React 反爬拦死?知乎 Draft.js 编辑器的完整破解过程(附代码)
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!