openclaw-deploy
npx skills add https://github.com/majiayu000/claude-arsenal --skill openclaw-deploy
Agent 安装分布
Skill 文档
OpenClaw è¿ç¨ä¸é®é¨ç½²
å¨è¿ç¨ Linux æå¡å¨ä¸èªå¨é¨ç½² OpenClaw + AI 模å + è天é¢éã
ç¬¬é¶æ¥ï¼è¾åºå»çæç¨
skill å¯å¨åï¼å¿ é¡»å è¾åºä»¥ä¸å夿¸ åï¼è®©ç¨æ·ç¥ééè¦ä»ä¹ï¼ç¶ååç¨ AskUserQuestion æ¶éä¿¡æ¯ï¼
# OpenClaw ä¸é®é¨ç½²
欢è¿ï¼é¨ç½²åä½ éè¦åå¤ä»¥ä¸ä¸è¥¿ï¼
| åºå· | åå¤ä»ä¹ | 说æ | å¿
éï¼ |
|------|----------|------|--------|
| 1 | ä¸å° Linux æå¡å¨ | æä½ 1GB å
å + 500MB ç£çï¼æ¯æ SSH ç»å½ | å¿
é |
| 2 | SSH å
å¯ç»å½ | ç¡®ä¿æ¬æºè½ `ssh user@host` ç´æ¥è¿ä¸ | å¿
é |
| 3 | AI 模å API Key | æºè°±GLM / DeepSeek / OpenAI / Claude / Kimi / éä¹ ä»»é | å¿
é |
| 4 | è天é¢é Bot Token | Telegram(@BotFather) æ Discord æ é£ä¹¦ï¼ä¹å¯ä»¥æä¸é
| å¯é |
| 5 | 代çå°å | ä¸å½å¤§éæå¡å¨ + æµ·å¤é¢é(Telegram/Discord)æ¶éè¦ | è§æ
åµ |
| 6 | æµè§å¨æ§å¶ | 让 Bot è½ææ§æµè§å¨æç´¢/æªå¾/填表ï¼éé¢å¤å®è£
Playwright | å¯é |
ç¬¬ä¸æ¥ï¼æ¶éä¿¡æ¯
ç¨ AskUserQuestion æ¶éï¼$ARGUMENTS å·²æä¾çè·³è¿ï¼ãå两轮é®ï¼
第ä¸è½®ï¼å¿ å¡« 3 项ï¼ï¼
ç¨ AskUserQuestion åæ¶é®ä»¥ä¸ 3 个é®é¢ï¼
- SSH è¿æ¥ä¿¡æ¯ï¼header: “SSH è¿æ¥”ï¼
- éé¡¹æ ¹æ®ä¸ä¸æå¨æçæï¼å¦ä¹åç¨è¿çæå¡å¨ï¼ï¼å åºé项”å ¶ä»æå¡å¨”
- AI 模åï¼header: “AI 模å”ï¼
- æºè°± GLM-5ï¼å½äº§ï¼æ é代çï¼
- DeepSeekï¼å½äº§ï¼æ é代çï¼
- OpenAI GPT-4oï¼éä»£çææµ·å¤æå¡å¨ï¼
- Anthropic Claudeï¼éä»£çææµ·å¤æå¡å¨ï¼
- è天é¢éï¼header: “è天é¢é”ï¼
- Telegramï¼é Bot Tokenï¼ä¸å½å¤§éé代çï¼
- Discordï¼é Bot Tokenï¼
- é£ä¹¦ï¼é Bot Tokenï¼
- æä¸é ç½®
- æµè§å¨æ§å¶ï¼header: “æµè§å¨”ï¼
- å¯ç¨ï¼Bot å¯ææ§æµè§å¨æç´¢/æªå¾/填表ï¼
- æä¸é ç½®
第äºè½®ï¼æ ¹æ®ç¬¬ä¸è½®ç»æè¿½é®ï¼ï¼
- å¦æç¨æ·æ²¡æä¾ API Key â é® API Key
- 妿éäºè天é¢é â é® Bot Token
- å¦æç¨æ·æ²¡æ Bot Token â ç»åºå建æç¨ï¼
- Telegramï¼æ¾ @BotFatherï¼å
/newbot - Discordï¼å» discord.com/developers å建 Application â Bot
- é£ä¹¦ï¼å» open.feishu.cn å建èªå»ºåºç¨
- Telegramï¼æ¾ @BotFatherï¼å
- å¦æç¨æ·æ²¡æ Bot Token â ç»åºå建æç¨ï¼
- 妿éäº Telegram/Discord 䏿å¡å¨å¨ä¸å½å¤§é â é®ä»£çå°å
- èªå¨å¤æï¼å¦æ SSH å°æå¡å¨å
curl -s --connect-timeout 3 https://api.telegram.org失败ï¼åå¤å®éè¦ä»£ç
- èªå¨å¤æï¼å¦æ SSH å°æå¡å¨å
ç¬¬äºæ¥ï¼ç¯å¢æ£æ¥
SSH è¿æ¥å°æå¡å¨ï¼åæ¡å½ä»¤è·åå ¨é¨ä¿¡æ¯ï¼
ssh <SSH_ARGS> "echo '=== CPU ===' && nproc && echo '=== å
å ===' && free -h && echo '=== ç£ç ===' && df -h / && echo '=== ç³»ç» ===' && uname -a && echo '=== Node.js ===' && node -v 2>/dev/null || echo 'æªå®è£
' && echo '=== npm ===' && npm -v 2>/dev/null || echo 'æªå®è£
' && echo '=== å
管çå¨ ===' && which pacman apt yum dnf 2>/dev/null && echo '=== OpenClaw ===' && openclaw --version 2>/dev/null || echo 'æªå®è£
'"
æä½è¦æ±ï¼1GB RAM + 500MB ç£çã䏿»¡è¶³ååç¥ç¨æ·å¹¶åæ¢ã
ç¬¬ä¸æ¥ï¼å®è£ Node.jsï¼å¦æªå®è£ ï¼
æ ¹æ®æ£æµå°çå 管çå¨ï¼
| å 管çå¨ | å½ä»¤ |
|---|---|
| pacman (Arch) | pacman -S --noconfirm nodejs npm |
| apt (Debian/Ubuntu) | curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && apt install -y nodejs |
| dnf (RHEL/Fedora) | dnf install -y nodejs npm |
| yum (CentOS) | curl -fsSL https://rpm.nodesource.com/setup_22.x | bash - && yum install -y nodejs |
å®è£
åéªè¯ï¼node -v && npm -vï¼ç¡®è®¤ Node.js >= 22ã
ç¬¬åæ¥ï¼å®è£ OpenClaw
curl -fsSL https://openclaw.ai/install.sh | bash
éè¦ï¼å®è£ èæ¬ä¼å°è¯å¯å¨äº¤äºå¼ onboarding wizardï¼å¨é TTY ç¯å¢ä¼æ¥
/dev/tty: No such device or addressé误ãè¿æ¯æ£å¸¸çï¼OpenClaw æ¬ä½å·²å®è£ æåã
éªè¯ï¼openclaw --version
ç¬¬äºæ¥ï¼åå ¥é ç½®æä»¶
ç´æ¥å ~/.openclaw/openclaw.jsonï¼ä¸ç¨äº¤äºå¼ wizardã
模åé 置模æ¿
{
"models": {
"mode": "merge",
"providers": {
"<PROVIDER_NAME>": {
"baseUrl": "<BASE_URL>",
"apiKey": "<API_KEY>",
"api": "openai-completions",
"models": [
{
"id": "<MODEL_ID>",
"name": "<DISPLAY_NAME>",
"reasoning": false,
"input": ["text"],
"contextWindow": 128000,
"maxTokens": 32000
}
]
}
}
},
"agents": {
"defaults": {
"model": {
"primary": "<PROVIDER_NAME>/<MODEL_ID>"
},
"memorySearch": {
"enabled": false
}
}
},
"gateway": {
"mode": "local"
}
}
å¸¸è§æ¨¡ååè
| Provider å | MODEL_ID | baseUrl |
|---|---|---|
| zhipu | glm-5 | https://open.bigmodel.cn/api/paas/v4 |
| openai | gpt-4o | https://api.openai.com/v1 |
| deepseek | deepseek-chat | https://api.deepseek.com/v1 |
| kimi | moonshot-v1-128k | https://api.moonshot.cn/v1 |
| qwen | qwen-max | https://dashscope.aliyuncs.com/compatible-mode/v1 |
| anthropic | claude-sonnet-4-5-20250929 | https://api.anthropic.com/v1 |
注æï¼Anthropic 模åç
apiåæ®µåºä¸º"anthropic-messages"èé"openai-completions"ã
åå ¥åç«å³ä¿®å¤æéï¼
mkdir -p ~/.openclaw/agents/main/sessions ~/.openclaw/credentials
chmod 700 ~/.openclaw
chmod 600 ~/.openclaw/openclaw.json
ç¬¬å æ¥ï¼å¯å¨ç½å ³ï¼systemdï¼
æé¡ºåºæ§è¡ï¼
# å®è£
systemd æå¡
openclaw gateway install
# å¯ç¨ lingerï¼éåº SSH åæå¡ä¸ä¼åï¼
loginctl enable-linger $(whoami)
# å¯å¨
export XDG_RUNTIME_DIR=/run/user/$(id -u)
systemctl --user start openclaw-gateway.service
çå¾ 3 ç§åéªè¯ï¼
systemctl --user status openclaw-gateway.service | head -10
确认 Active: active (running)ã
è½®æ¢ device token
ç½å ³é¦æ¬¡å¯å¨åï¼è½®æ¢ operator token ä¿®å¤å¯è½ç认è¯é®é¢ï¼
# å
è·å device ID
DEVICE_ID=$(openclaw devices list 2>&1 | grep -oP '[a-f0-9]{40,}')
# è½®æ¢ token
openclaw devices rotate --role operator --device "$DEVICE_ID"
ç¬¬ä¸æ¥ï¼é ç½®è天é¢éï¼å¦éè¦ï¼
æ ¹æ®ç¨æ·éæ©çé¢éæ§è¡å¯¹åºé ç½®ã
7a. 设置é¢é
Telegramï¼
openclaw config set channels.telegram.enabled true
openclaw config set channels.telegram.botToken '<BOT_TOKEN>'
openclaw config set channels.telegram.dmPolicy pairing
Discordï¼
openclaw config set channels.discord.enabled true
openclaw config set channels.discord.botToken '<BOT_TOKEN>'
openclaw config set channels.discord.dmPolicy pairing
é£ä¹¦ï¼
openclaw config set channels.feishu.enabled true
openclaw config set channels.feishu.token '<BOT_TOKEN>'
openclaw config set channels.feishu.dmPolicy pairing
7b. é 置代çï¼ä¸å½å¤§éæå¡å¨ + æµ·å¤é¢éæ¶å¿ é¡»ï¼
éç¨åºæ¯ï¼æå¡å¨å¨ä¸å½å¤§éï¼ä¸é¢éæ¯ Telegram æ Discordï¼éè®¿é®æµ·å¤ APIï¼ã é£ä¹¦æ¯å½å æå¡ï¼ä¸éè¦ä»£çã
å æµè¯æ¯å¦éè¦ä»£çï¼èªå¨å¤æï¼ï¼
# Telegram
curl -s --connect-timeout 3 https://api.telegram.org/bot<BOT_TOKEN>/getMe
# Discord
curl -s --connect-timeout 3 https://discord.com/api/v10/users/@me -H "Authorization: Bot <BOT_TOKEN>"
å¦æè¶ æ¶/失败ï¼è¯´æéè¦ä»£çãç¨ç¨æ·æä¾çä»£çæµè¯ï¼
export http_proxy='<PROXY_URL>' && export https_proxy='<PROXY_URL>'
curl -s --connect-timeout 5 https://api.telegram.org/bot<BOT_TOKEN>/getMe
确认è¿åæååï¼åå ¥ systemd overrideã
éè¦ï¼proxy.conf å¿ é¡»ä¸æ¬¡æ§å宿æç¯å¢åéï¼ä»£ç + no_proxy + DISPLAYï¼ï¼ ä¸è¦å夿¬¡è¿½å ï¼åç»æµè§å¨æ¥éª¤ä¹ä¸éè¦åæ¹è¿ä¸ªæä»¶ã
mkdir -p ~/.config/systemd/user/openclaw-gateway.service.d
cat > ~/.config/systemd/user/openclaw-gateway.service.d/proxy.conf << EOF
[Service]
Environment="http_proxy=<PROXY_URL>"
Environment="https_proxy=<PROXY_URL>"
Environment="no_proxy=127.0.0.1,localhost,::1"
Environment="NO_PROXY=127.0.0.1,localhost,::1"
Environment="DISPLAY=:99"
EOF
为ä»ä¹è¦
no_proxyï¼æ²¡æå®ï¼OpenClaw è¿æ¬å° Chrome CDP 端å£ä¹ä¼èµ°ä»£çï¼ å¯¼è´æµè§å¨å¯å¨æåä½ OpenClaw æ£æµä¸å°ï¼æ¥Failed to start Chrome CDPã å³ä½¿å½åä¸é æµè§å¨ï¼ä¹è¦å ä¸no_proxyï¼é²æ¢åç»å¼å¯æµè§å¨æ¶è¸©åã
为ä»ä¹è¦
DISPLAY=:99ï¼æµè§å¨éè¦æ¾ç¤ºæå¡å¨ï¼å³ä½¿ headless 模å¼ä¹éè¦ã 妿ä¸é æµè§å¨ï¼è¿ä¸ªåéæ å®³ã
7c. éå¯ç½å ³ï¼å¿ é¡»éè¿ systemdï¼ï¼
å ³é®åç¹ï¼
openclaw config setä¼è§¦åå é¨çéå¯ï¼ä½çéå¯ä¸ä¼å è½½ systemd çç¯å¢åéï¼ä»£çï¼ã æææ¶åé¢é/代ççé ç½®æ¹å®åï¼å¿ é¡»ç¨systemctl --user restartæ¥éå¯ã
export XDG_RUNTIME_DIR=/run/user/$(id -u)
systemctl --user daemon-reload
systemctl --user restart openclaw-gateway.service
7d. éªè¯é¢éè¿æ¥
çå¾ 5 ç§åï¼
openclaw channels status
确认è¾åºå
å« enabled, configured, runningã
妿çå° fetch failed æ Network request failedï¼ä»£ç没çæï¼æ£æ¥ proxy.conf 并确认æ¯éè¿ systemctl éå¯çã
7e. é å¯¹ç¨æ·
è®©ç¨æ·å¨å¯¹åºé¢éç» Bot å䏿¡æ¶æ¯ãBot ä¼åå¤é 对ç ã
å ³é®åç¹ï¼é 对å½ä»¤æ¯
openclaw pairing approve <channel> <CODE>ï¼ ä¸æ¯openclaw devices approve <CODE>ï¼é£ä¸ªä¼æ¥unknown requestIdï¼ã
# æ¥çå¾
é
对å表ï¼å¿
é¡»æå®é¢éåï¼
openclaw pairing list <channel>
# ä¾å¦ï¼openclaw pairing list telegram
# æ¹åé
对
openclaw pairing approve <channel> <PAIRING_CODE>
# ä¾å¦ï¼openclaw pairing approve telegram BAEWET79
é å¯¹ç æææçº¦ 1 å°æ¶ãå¦æè¿æï¼è®©ç¨æ·éæ°åæ¶æ¯å³å¯çææ°ç ã
ç¬¬å «æ¥ï¼é ç½®æµè§å¨æ§å¶ï¼å¯éï¼
让 Bot è½ææ§æµè§å¨ï¼æ§è¡æç´¢ãæªå¾ã填表çæä½ã å¦æç¬¬ä¸æ¥ç¨æ·éäºãæä¸é ç½®ãï¼è·³è¿æ¤æ¥ã
8a. å®è£ Playwright Chromium + Xvfb
ä¸è¦ç¨ç³»ç»èªå¸¦ç Chromiumãæ»å¨åè¡çï¼Arch çï¼ä¼åºç° ICU/libFLAC çåºçæ¬ä¸å¹é ï¼ ç¨³å®åè¡çä¹å¯è½çæ¬è¿æ§ãç»ä¸ç¨ Playwright èªå¸¦ç Chromiumï¼ä¸æ¡å½ä»¤è§£å³ã
# å®è£
Playwright Chromiumï¼èªå¸¦ææä¾èµï¼ä¸ä¾èµç³»ç»åºï¼
npx playwright install chromium
# å®è£
Xvfb èææ¾ç¤ºï¼æ 头æå¡å¨å¿
é¡»ï¼
# Arch:
pacman -S --noconfirm xorg-server-xvfb
# Debian/Ubuntu:
apt install -y xvfb
éªè¯ Playwright Chromium å¯è¿è¡ï¼
PLAYWRIGHT_CHROME=$(find ~/.cache/ms-playwright/chromium-*/chrome-linux/chrome 2>/dev/null | head -1)
$PLAYWRIGHT_CHROME --version
8b. å建 Chromium Wrapper + 代çä¸ç»§ï¼éè¦ä»£çæ¶ï¼
为ä»ä¹éè¦ wrapperï¼
- OpenClaw èªå¨æ£æµ
/usr/bin/chromiumæ¥å¯å¨æµè§å¨ï¼wrapper 让å®ç¨ Playwright çæ¬- Chromium 䏿¯æ
http_proxyURL ä¸åµå ¥ç认è¯ï¼user:pass@hostï¼ï¼ä¼æ¥ERR_INVALID_AUTH_CREDENTIALS- wrapper èªå¨ unset 代çç¯å¢åéï¼æ¹ç¨
--proxy-serveræåæ¬å°æ 认è¯ä»£çä¸ç»§
妿éè¦ä»£çï¼ä¸å½å¤§éè®¿é®æµ·å¤ç«ç¹ï¼ï¼å æå»ºæ¬å°ä»£çä¸ç»§ï¼
# å建代çä¸ç»§èæ¬ï¼Node.jsï¼å»æè®¤è¯å±ï¼Chrome ç´è¿ï¼
cat > ~/.openclaw/proxy-relay.js << 'RELAYEOF'
const http = require("http");
const net = require("net");
const UPSTREAM_HOST = process.env.PROXY_HOST || "127.0.0.1";
const UPSTREAM_PORT = parseInt(process.env.PROXY_PORT || "7890", 10);
const UPSTREAM_USER = process.env.PROXY_USER || "";
const UPSTREAM_PASS = process.env.PROXY_PASS || "";
const LOCAL_PORT = parseInt(process.env.RELAY_PORT || "7891", 10);
const authHeader = UPSTREAM_USER
? "Basic " + Buffer.from(UPSTREAM_USER + ":" + UPSTREAM_PASS).toString("base64")
: null;
const server = http.createServer((req, res) => {
const opts = { host: UPSTREAM_HOST, port: UPSTREAM_PORT, path: req.url,
method: req.method, headers: { ...req.headers } };
if (authHeader) opts.headers["Proxy-Authorization"] = authHeader;
const proxy = http.request(opts, (pRes) => { res.writeHead(pRes.statusCode, pRes.headers); pRes.pipe(res); });
proxy.on("error", (e) => { res.writeHead(502); res.end(String(e)); });
req.pipe(proxy);
});
server.on("connect", (req, clientSocket, head) => {
const connectReq = "CONNECT " + req.url + " HTTP/1.1\r\nHost: " + req.url + "\r\n"
+ (authHeader ? "Proxy-Authorization: " + authHeader + "\r\n" : "") + "\r\n";
const proxySocket = net.connect(UPSTREAM_PORT, UPSTREAM_HOST, () => { proxySocket.write(connectReq); });
let buf = Buffer.alloc(0);
const onData = (chunk) => {
buf = Buffer.concat([buf, chunk]);
const idx = buf.indexOf("\r\n\r\n");
if (idx === -1) return;
proxySocket.removeListener("data", onData);
const resp = buf.slice(0, idx).toString();
const rest = buf.slice(idx + 4);
if (resp.includes(" 200 ")) {
clientSocket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
if (rest.length) clientSocket.write(rest);
if (head.length) proxySocket.write(head);
proxySocket.pipe(clientSocket); clientSocket.pipe(proxySocket);
} else { clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n"); proxySocket.end(); }
};
proxySocket.on("data", onData);
proxySocket.on("error", () => clientSocket.destroy());
clientSocket.on("error", () => proxySocket.destroy());
});
server.listen(LOCAL_PORT, "127.0.0.1", () => {
console.log("proxy-relay listening on 127.0.0.1:" + LOCAL_PORT + " -> " + UPSTREAM_HOST + ":" + UPSTREAM_PORT);
});
RELAYEOF
# å建 systemd æå¡ï¼ç¨å®é
ç代çä¿¡æ¯æ¿æ¢åéï¼
cat > ~/.config/systemd/user/proxy-relay.service << EOF
[Unit]
Description=Local Proxy Relay (auth-stripping for Chrome)
Before=openclaw-gateway.service
[Service]
ExecStart=/usr/bin/node /root/.openclaw/proxy-relay.js
Environment="PROXY_HOST=<UPSTREAM_PROXY_HOST>"
Environment="PROXY_PORT=<UPSTREAM_PROXY_PORT>"
Environment="PROXY_USER=<UPSTREAM_PROXY_USER>"
Environment="PROXY_PASS=<UPSTREAM_PROXY_PASS>"
Environment="RELAY_PORT=7891"
Restart=always
RestartSec=3
[Install]
WantedBy=default.target
EOF
export XDG_RUNTIME_DIR=/run/user/$(id -u)
systemctl --user daemon-reload
systemctl --user enable --now proxy-relay.service
# éªè¯ä¸ç»§å·¥ä½
curl -s --connect-timeout 5 -x http://127.0.0.1:7891 https://api.telegram.org | head -1
æ¶æè¯´æï¼
Chrome --proxy-server=127.0.0.1:7891 â proxy-relayï¼æ 认è¯ï¼â 䏿¸¸ä»£çï¼å¸¦è®¤è¯ï¼â æµ·å¤ç½ç«
å建 wrapperï¼æ ¹æ®æ¯å¦éè¦ä»£çï¼éæ©å¯¹åºçæ¬ï¼ï¼
# å¤ä»½ç³»ç» chromiumï¼å¦ææï¼
mv /usr/bin/chromium /usr/bin/chromium.system 2>/dev/null
# è·å Playwright Chrome è·¯å¾
PLAYWRIGHT_CHROME=$(find ~/.cache/ms-playwright/chromium-*/chrome-linux/chrome 2>/dev/null | head -1)
# === éè¦ä»£çççæ¬ ===
cat > /usr/bin/chromium << EOF
#!/bin/bash
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY
exec $PLAYWRIGHT_CHROME --proxy-server=http://127.0.0.1:7891 "\$@"
EOF
# === ä¸éè¦ä»£çççæ¬ ===
# cat > /usr/bin/chromium << EOF
# #!/bin/bash
# unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY
# exec $PLAYWRIGHT_CHROME "\$@"
# EOF
chmod +x /usr/bin/chromium
# éªè¯
/usr/bin/chromium --version
注æï¼å wrapper æä»¶æ¶é¿å éè¿ SSH ä¼ é
#!/bin/bashï¼ æäº shellï¼zshï¼ä¼æ!转ä¹ä¸º\!ã建议ç¨scpæå¨è¿ç¨æå¡å¨ä¸ç´æ¥ç¼è¾ã
8c. å¯å¨ Xvfb æå¡
cat > ~/.config/systemd/user/xvfb.service << 'EOF'
[Unit]
Description=Xvfb Virtual Framebuffer
Before=openclaw-gateway.service
[Service]
ExecStart=/usr/bin/Xvfb :99 -screen 0 1280x720x24 -nolisten tcp
Restart=always
RestartSec=3
[Install]
WantedBy=default.target
EOF
export XDG_RUNTIME_DIR=/run/user/$(id -u)
systemctl --user daemon-reload
systemctl --user enable --now xvfb.service
8d. é ç½® OpenClaw æµè§å¨ï¼ä¸ä¸ªå¿ 设项 + profileï¼
ä¸ä¸ªé 置缺ä¸ä¸å¯ï¼å¦å Chrome æ æ³å¨æ 头æå¡å¨ä¸ä»¥ root è¿è¡ï¼
openclaw config set browser.enabled true
openclaw config set browser.headless true # æ 头模å¼ï¼ä¸å¼ä¼å°è¯æå¼ GUI
openclaw config set browser.noSandbox true # root è¿è¡å¿
é¡»ï¼å¦å Chrome éé»å´©æº
å建 headless profileï¼ä½¿ç¨ openclaw 驱å¨ï¼ä¸ç¨ Chrome æ©å±ï¼ï¼
openclaw browser create-profile --name headless --driver openclaw --color '#0066CC'
openclaw config set browser.defaultProfile headless
ä¸è¦ç¨é»è®¤ç extension driverãextension driver éè¦å¨ Chrome éå®è£ OpenClaw æ©å±ï¼ æ 头æå¡å¨ä¸ä¸å¯è½æä½ã
--driver openclawä½¿ç¨ Playwright ç´æ¥é©±å¨ã
8e. ç¡®ä¿ systemd ç¯å¢åé宿´
å¦æç¬¬ 7 æ¥å·²ç»åäº proxy.confï¼å«
no_proxyåDISPLAY=:99ï¼ï¼è¿éä¸éè¦åæ¹ã å¦æç¬¬ 7 æ¥æ²¡é 代çï¼ä¸éè¦ä»£ççåºæ¯ï¼ï¼è¿éåªéåDISPLAYï¼
# ä»
å½ç¬¬ 7 æ¥æ²¡åè¿ proxy.conf æ¶æéè¦
mkdir -p ~/.config/systemd/user/openclaw-gateway.service.d
cat > ~/.config/systemd/user/openclaw-gateway.service.d/proxy.conf << 'EOF'
[Service]
Environment="DISPLAY=:99"
EOF
8f. æ¸ ç + éªè¯é ç½® + éå¯
éè¦ï¼å è¿è¡
openclaw doctor --fixæ¸ çå¯è½çæ æé ç½® keyï¼ é¿å ç½å ³å é ç½®æ ¡éªå¤±è´¥åå¤å´©æºéå¯ã
# æ¸
çæ æé
ç½®
openclaw doctor --fix
# ææå¯è½æ®çç Chrome è¿ç¨
killall -9 chrome chrome_crashpad 2>/dev/null
rm -f ~/.openclaw/browser/headless/user-data/SingletonLock 2>/dev/null
# éå¯ç½å
³
export XDG_RUNTIME_DIR=/run/user/$(id -u)
systemctl --user daemon-reload
systemctl --user restart openclaw-gateway.service
sleep 5
# æµè¯å¯¼èªï¼ç¨ç®åç«ç¹ï¼é¦æ¬¡è¿æ¥è¾æ
¢å±æ£å¸¸ï¼
openclaw browser navigate https://example.com --timeout 60000
# æµè¯å¿«ç
§
openclaw browser snapshot | head -20
# ç¡®è®¤ç¶æï¼åºæ¾ç¤º running: trueï¼
openclaw browser status
8g. ä½åèè®¾å¤æ§è½è°ä¼ï¼ARM/æ èæ´¾çï¼
éç¨åºæ¯ï¼æ èæ´¾ãARM å¼åæ¿çä½åè设å¤ãx86 æå¡å¨é常ä¸éè¦ã æ ¸å¿é®é¢ï¼Chrome 使ç¨
swiftshader-webglï¼CPU 软件渲æï¼ï¼ARM CPU å¤çå¤æé¡µé¢ææ ¢ã å å䏿¯ç¶é¢ï¼8GB è¶³å¤ï¼ï¼CPU ææ¯ã
é®é¢ 1ï¼æµè§å¨æä½è¶ æ¶ 20 ç§ä¸å¤
OpenClaw 硬ç¼ç äº 20 ç§è¶
æ¶ï¼timeoutMs: 2e4ï¼ï¼ä½åè设å¤ä¸éè¦ 60 ç§ã
# ä¿®æ¹æææµè§å¨æä½è¶
æ¶ï¼20s â 60s
for f in pi-embedded-*.js reply-*.js; do
FILE="/usr/lib/node_modules/openclaw/dist/$f"
[ -f "$FILE" ] && sed -i 's/timeoutMs: 2e4/timeoutMs: 6e4/g' "$FILE"
done
# ä¿®æ¹æµè§å¨ CLI å½ä»¤è¶
æ¶
for f in browser-cli-*.js; do
FILE="/usr/lib/node_modules/openclaw/dist/$f"
[ -f "$FILE" ] && sed -i 's/timeoutMs: 2e4/timeoutMs: 6e4/g; s/?? 2e4/?? 6e4/g' "$FILE"
done
# ä¿®æ¹é»è®¤ä»£çè¶
æ¶å¸¸é
sed -i 's/DEFAULT_BROWSER_PROXY_TIMEOUT_MS = 2e4/DEFAULT_BROWSER_PROXY_TIMEOUT_MS = 6e4/g' \
/usr/lib/node_modules/openclaw/dist/pi-embedded-*.js \
/usr/lib/node_modules/openclaw/dist/reply-*.js
é®é¢ 2ï¼Playwright CDP è¿æ¥è¶ æ¶å¤ªç
Playwright è¿æ¥ Chrome æ 3 次éè¯ï¼5s/7s/9sï¼ï¼ARM 设å¤ä¸ä¸å¤ãæ¹ä¸º 15s/20s/25sï¼
# å¢å Playwright CDP è¿æ¥è¶
æ¶
sed -i 's/const timeout = 5e3 + attempt \* 2e3/const timeout = 15e3 + attempt * 5e3/g' \
/usr/lib/node_modules/openclaw/dist/pw-ai-*.js
é®é¢ 3ï¼Chrome éå¯åæ¢å¤æ§æ ç¾
Chrome ä» user-data æ¢å¤ä¸æ¬¡ä¼è¯çæææ ç¾é¡µï¼å¨ä½åè设å¤ä¸å¤æ ç¾ä¼èå°½ CPUã æ¯æ¬¡éå¯ç½å ³åéè¦æ¸ çï¼
# å
³éææ Chrome æ ç¾ï¼ä¿çä¸ä¸ªç©ºç½é¡µï¼
curl -s http://127.0.0.1:18801/json/list 2>/dev/null | \
python3 -c "
import sys,json,urllib.request
try:
tabs=json.load(sys.stdin)
for t in tabs[1:]:
urllib.request.urlopen(f'http://127.0.0.1:18801/json/close/{t[\"id\"]}')
print(f'Closed {len(tabs)-1} tabs')
except: pass
" 2>/dev/null
注æï¼ä»¥ä¸æºç ä¿®æ¹ä¼å¨ OpenClaw æ´æ°å被è¦çï¼éè¦éæ°æ§è¡ã
ä½åèè®¾å¤æµè§å¨ä½¿ç¨å»ºè®®ï¼
- é¿å éå SPAï¼Google NewsãTwitter çï¼ï¼è¶ è¿ 60 ç§ä»ä¼è¶ æ¶
- ä¼å ç¨è½»é级/ææ¬çç½ç«ï¼CNN LiteãRSS feedsãAPI æ¥å£ï¼
- ç®å页é¢ï¼example.comãç¾åº¦ï¼é常 3-5 ç§å 宿
- 馿¬¡æµè§å¨æä½è¾æ ¢ï¼Playwright éå»ºç« CDP è¿æ¥ï¼ï¼åç»æä½å¿«å¾å¤
8h. X/Twitter ç»å½ï¼å¯éï¼
éç¨åºæ¯ï¼è®© Bot è½ä»¥å·²ç»å½èº«ä»½æµè§ X/Twitterï¼æ¥çæ¶é´çº¿ãæç´¢çï¼ã éè¦å 宿 8a-8f çæµè§å¨é ç½®ã
åç½®æ¡ä»¶ï¼ç¨æ·éæä¾ X/Twitter ç auth_tokenï¼40 ä½åå
è¿å¶ï¼ã
è¿ä¸ª token å¯ä»å·²ç»å½æµè§å¨ç Cookies 䏿åï¼å¼åè
å·¥å
· â Application â Cookies â x.com â auth_tokenï¼ã
æ ¸å¿ç»éªï¼ä¸è¦å°è¯å¨æå¡å¨ä¸èªå¨åç»å½æµç¨ï¼ ç´æ¥æ³¨å ¥ auth_token æ¯å¯ä¸å¯é æ¹æ¡ã æä»¬å°è¯è¿ 7+ ç§ç»å½æ¹æ¡å ¨é¨å¤±è´¥ï¼è§è¸©åæ»ç» 22-30ï¼ï¼åå å æ¬ï¼
- X çç»å½é¡µå¨ ARM + swiftshader 䏿 æ³æ¸²æ
- API ç»å½æµç¨ä¼è§¦å IP éé¢ï¼error 399ï¼
- Python HTTP 客æ·ç«¯è¢« Cloudflare TLS æçº¹è¯å«æ¦æª
- Chrome è·¨å请æ±ï¼CORSï¼éå¶æ æ³ç»è¿
- CDP Fetch æ¦æªå¼å¯å fetch è°ç¨å ¨é¨æ¥é
è·å auth_token
ç¨æ·éè¦å¨èªå·±ççµèæµè§å¨ä¸è·å auth_tokenï¼æå¡å¨ä¸æ æ³å®æç»å½ï¼ï¼
- å¨çµèæµè§å¨ç»å½ x.com
- æå¼å¼åè
å·¥å
·ï¼F12ï¼â Application â Cookies â
https://x.com - æ¾å°
auth_tokenï¼å¤å¶å¼ï¼40 ä½åå è¿å¶å符串ï¼
å ³é®çè§£ï¼ä¹å”æåç»å½”å®é ä¸ä¸æ¯å¨æå¡å¨ä¸å®æç»å½ï¼èæ¯å¤ç¨äºä¸ä¸ªå·²æçææ auth_tokenã æ¬è´¨æ¯”è´´äºä¸å¼ ææçé¨ç¥¨”ï¼ä¸æ¯”éæ°ä¹°ç¥¨”ãæå¡å¨ä¸æ²¡æä»»ä½å¯é æ¹å¼å®æ X çç»å½æµç¨ã
æ³¨å ¥ auth_token å° Chrome
# /tmp/x-inject-token.py â éè¿ CDP 注å
¥ auth_token
import json, socket, struct, hashlib, base64, time, os, urllib.request
CDP_URL = "http://127.0.0.1:18801"
AUTH_TOKEN = "<ç¨æ·æä¾çauth_token>"
# ... CDP ç±»ï¼è§ä¸æ¹å®æ´ä»£ç ï¼...
# 1. æ¸
餿§ç x.com/twitter.com cookies
all_ck = c.cmd("Network.getAllCookies")
for ck in all_ck.get("cookies", []):
dom = ck.get("domain", "")
if "x.com" in dom or "twitter.com" in dom:
c.cmd("Network.deleteCookies", {"name": ck["name"], "domain": dom})
# 2. 注å
¥ auth_tokenï¼å¿
须带 expires åæ°ï¼ï¼
expires = time.time() + 365 * 86400
for dom in [".x.com", ".twitter.com"]:
c.cmd("Network.setCookie", {
"name": "auth_token", "value": AUTH_TOKEN,
"domain": dom, "path": "/", "secure": True, "httpOnly": True,
"expires": expires, "sameSite": "None"
})
# 3. 导èªå° x.com/home 触åä¼è¯å»ºç«
c.cmd("Page.navigate", {"url": "https://x.com/home"})
time.sleep(25) # ARM 设å¤éè¦æ´é¿çå¾
# 4. éªè¯ï¼é¡µé¢æ é¢åºä¸º "(N) Home / X"ï¼ä¸ cookies å
å« ct0 å twid
all_ck = c.cmd("Network.getAllCookies")
# ä» Network å±è¯»å cookiesï¼ct0 æ¯ httpOnlyï¼JS 读ä¸å°ï¼
# 5. ä¿åå
¨é¨ cookiesï¼å« ct0ãtwid çä¼è¯åçæç cookieï¼
x_ck = {}
for ck in all_ck.get("cookies", []):
dom = ck.get("domain", "")
if "x.com" in dom or "twitter.com" in dom:
x_ck[ck["name"]] = ck["value"]
with open(os.path.expanduser("~/.openclaw/x-cookies.json"), "w") as f:
json.dump(x_ck, f, indent=2)
# 6. ååå
¨é¨ cookies 并带 expiresï¼ç¡®ä¿æä¹
åå° Chrome ç¨æ·ç®å½ï¼
for name, val in x_ck.items():
if isinstance(val, str):
for dom in [".x.com", ".twitter.com"]:
c.cmd("Network.setCookie", {
"name": name, "value": val, "domain": dom,
"path": "/", "secure": True,
"httpOnly": name in ("auth_token", "ct0"),
"expires": expires, "sameSite": "None"
})
Cookie æä¹ åï¼å ³é®ï¼ï¼
大åï¼
Network.setCookieä¸å¸¦expiresåæ°æ¶ï¼cookie åªåå¨å åä¸ï¼ Chrome éå¯åå ¨é¨ä¸¢å¤±ï¼Twitter æ£æµå° session æå¼ä¼åé auth_tokenã 䏿¦ token 被åéå°±æ°¸ä¹ å¤±æï¼å¿ é¡»ç¨æ·éæ°å¨çµèä¸ç»å½è·åæ° tokenã
å¿ é¡»åç两件äºï¼
- 注å
¥æ¶å¿
须带
expiresåæ°ï¼è®¾ä¸º 1 å¹´åï¼ï¼è®© Chrome åå ¥ç£çæä¹ å - ç»å½æååååå
¨é¨ cookiesï¼å¯¼èªå° x.com/home åï¼Twitter ä¼çæ
ct0ãtwidçæ° cookieï¼ è¿äº cookie ä¹éè¦ç¨Network.setCookie+expiresååä¸éï¼å¦åå®ä»¬ä¹æ¯å åæ
éªè¯ cookie æ¯å¦æä¹ åï¼ éå¯ Chrome åï¼æ£æ¥ cookies æ¯å¦è¿å¨ï¼
all_ck = c.cmd("Network.getAllCookies")
auth = [ck for ck in all_ck.get("cookies", []) if ck["name"] == "auth_token"]
print(f"auth_token exists: {len(auth) > 0}")
éªè¯æåçæ å¿
- 页颿 é¢å
å«
Home / Xï¼ä¸æ¯Loginæç©ºç½é¡µï¼ - Cookies ä¸åºç°
ct0ï¼CSRF tokenï¼åtwidï¼ç¨æ· IDï¼ - URL ä¿æå¨
x.com/homeï¼æ²¡è¢«éå®åå°ç»å½é¡µï¼
ä¿å cookies ä¾å ¶ä»å·¥å ·ä½¿ç¨ï¼
# cookies ä¿åä½ç½®
~/.openclaw/x-cookies.json
éè¦ï¼
ct0cookie æ¯ httpOnly çï¼åªè½éè¿ CDPNetwork.getAllCookies读åï¼ ä¸è½ç¨document.cookie读ï¼ä¼è¿å空ï¼ãè¿æ¯ä¸ä¸ªå¸¸è§è¯¯å¤ââçå°ct0: none就以为ç»å½å¤±è´¥ï¼ å®é ä¸é¡µé¢æ é¢Home / Xå·²ç»è¯æç»å½æåäºã
å®è£ x-tweet-fetcher skillï¼å¯éï¼ï¼
让 Bot è½éè¿å½ä»¤è·å X/Twitter æ¨æå 容ï¼
# æå¨ä¸è½½å®è£
ï¼clawhub install ç»å¸¸éé¢ï¼
SKILL_DIR="/usr/lib/node_modules/openclaw/skills/x-tweet-fetcher"
mkdir -p "$SKILL_DIR/scripts"
# ä¸è½½ SKILL.md å fetch_tweet.py
curl -sL "https://raw.githubusercontent.com/ythx-101/x-tweet-fetcher/main/SKILL.md" \
-o "$SKILL_DIR/SKILL.md"
curl -sL "https://raw.githubusercontent.com/ythx-101/x-tweet-fetcher/main/scripts/fetch_tweet.py" \
-o "$SKILL_DIR/scripts/fetch_tweet.py"
chmod +x "$SKILL_DIR/scripts/fetch_tweet.py"
# éªè¯
openclaw skills list 2>&1 | grep tweet
åï¼
fetch_tweet.py使ç¨urllib.request.urlopen()ï¼è¿ä¸ªå½æ°ä¸ä¼èªå¨ä½¿ç¨https_proxyç¯å¢åéã 妿æå¡å¨éè¦ä»£çæè½è®¿é®å¤ç½ï¼å¿ é¡»æå¨æ·»å ProxyHandlerï¼
# å¨ fetch_tweet.py ç import é¨åå import os
# å¨ urlopen ä¹åå ï¼
proxy_url = os.environ.get("https_proxy") or os.environ.get("http_proxy") or ""
if proxy_url:
opener = urllib.request.build_opener(
urllib.request.ProxyHandler({"https": proxy_url, "http": proxy_url})
)
else:
opener = urllib.request.build_opener()
# ç¶åç¨ opener.open(url) æ¿æ¢ urllib.request.urlopen(url)
ç¬¬ä¹æ¥ï¼æç»éªè¯
# 1. å¥åº·æ£æ¥
openclaw health
# 2. é¢éç¶æ
openclaw channels status
# 3. æµè¯æ¨¡åè¿éï¼å½ä»¤è¡ï¼
openclaw agent --local --agent main -m 'ä½ å¥½ï¼ç®çç¡®è®¤ä½ æ¯ä»ä¹æ¨¡å'
# 4. systemd æå¡ç¶æ
export XDG_RUNTIME_DIR=/run/user/$(id -u)
systemctl --user status openclaw-gateway.service | head -5
# 5. æµè§å¨ç¶æï¼å¦å·²é
ç½®ï¼
openclaw browser status
å ¨é¨éè¿åï¼è¾åºæ»ç»è¡¨æ ¼ï¼
| é¡¹ç® | ç¶æ |
|---|---|
| OpenClaw | çæ¬å· |
| 模å | provider/model-id |
| ç½å ³ | systemd active (running) |
| Linger | å·²å¯ç¨ |
| é¢é | é¢éå + running |
| Bot 龿¥ | t.me/xxx_bot |
| 代ç | æ/æ |
| æµè§å¨ | running / æªé ç½® |
ä¿ååè¯
å¨ç¨æ·æ¬å°å·¥ä½ç®å½ä¿åä¸ä»½åè¯å¤å¿å½ï¼
æä»¶åï¼openclaw-credentials.txt
å
å®¹ï¼æå¡å¨å°åãBot åç§°ãBot Tokenãæ¨¡å provider
è¸©åæ»ç»ï¼ææµç¨é¡ºåºï¼
| ç¼å· | å | åå | æ£ç¡®åæ³ |
|---|---|---|---|
| 1 | å®è£
èæ¬æ¥ /dev/tty é误 |
é交äºå¼ SSH æ TTY | 忽ç¥ï¼OpenClaw å·²è£ å¥½ï¼æå¨åé ç½® |
| 2 | openclaw channels add --channel telegram æ¥ Unknown channel |
Telegram 䏿¯éè¿ channels add é
ç½®ç |
ç¨ openclaw config set channels.telegram.* |
| 3 | Telegram API è¿ä¸ä¸ï¼fetch failedï¼ |
ä¸å½å¤§éæ æ³ç´è¿ api.telegram.org | å¿ é¡»é 代çï¼åå ¥ systemd ç¯å¢åé |
| 4 | 代çé
äºä½éå¯åè¿æ¯ fetch failed |
openclaw config set 触åçéå¯ä¸å è½½ systemd ç¯å¢åé |
å¿
é¡»ç¨ systemctl --user restart |
| 5 | openclaw devices approve <CODE> æ¥ unknown requestId |
ç¨éå½ä»¤äº | æ£ç¡®å½ä»¤ï¼openclaw pairing approve telegram <CODE> |
| 6 | openclaw pairing list æ¥ Channel required |
å¿ é¡»æå®é¢éåæ° | openclaw pairing list telegram |
| 7 | é
ç½®éªè¯æ¥é dmPolicy="open" requires allowFrom to include "*" |
open 模å¼éè¦æ¾å¼è®¾ç½® allowFrom | ç¨ pairing 模å¼ï¼ä¸è¦æ¹æ open |
| 8 | gateway éè¦ gateway.mode æè½å¯å¨ |
æå¨åé ç½®æ¶æ¼äº | é
ç½®æä»¶éå "gateway": {"mode": "local"} |
| 9 | State integrity æ¥ç®å½ç¼ºå¤± |
馿¬¡å®è£ æªåå»ºå¿ è¦ç®å½ | mkdir -p ~/.openclaw/agents/main/sessions ~/.openclaw/credentials |
| 10 | éåº SSH åç½å ³åæ¢ | systemd user session æ linger | loginctl enable-linger |
| 11 | ç³»ç» Chromium å¯å¨æ¥åºçæ¬ä¸å¹é | Arch çæ»å¨åè¡ç ICU/libFLAC çæ¬ä¸å ¼å®¹ | ç¨ Playwright èªå¸¦ Chromiumï¼å建 wrapper æ¿æ¢ /usr/bin/chromium |
| 12 | Chrome extension relay not reachable at 127.0.0.1:18792 |
é»è®¤ profile ç¨ extension driverï¼éè¦ Chrome æ©å± | å建 headless profileï¼--driver openclawï¼ç¨ Playwright ç´æ¥é©±å¨ï¼ |
| 13 | Failed to start Chrome CDP on port 18801ï¼Chrome å·²å¯å¨ä½æ£æµä¸å°ï¼ |
http_proxy å¯¼è´ OpenClaw è¿ localhost CDP ä¹èµ°ä»£ç |
systemd ç¯å¢åéå no_proxy=127.0.0.1,localhost,::1 |
| 14 | æµè§å¨å¯¼èªæ¥ net::ERR_INVALID_AUTH_CREDENTIALS |
Chromium 䏿¯æ http_proxy URL ä¸ç user:pass@ è®¤è¯æ ¼å¼ |
wrapper èæ¬ä¸ unset http_proxy https_proxy |
| 15 | browser.headless å browser.noSandbox æªè®¾ç½® |
é»è®¤é½æ¯ falseï¼root æ 头è¿è¡å¿ é¡»å¼å¯ | openclaw config set browser.headless true + browser.noSandbox true |
| 16 | æµè§å¨æä½è¶
æ¶ timed out after 20000ms |
OpenClaw 硬ç¼ç 20 ç§è¶ æ¶ï¼ARM è®¾å¤ CPU 软件渲æå¤ªæ ¢ | ä¿®æ¹æºç timeoutMs: 2e4 â 6e4ï¼è§ 8g èï¼ |
| 17 | Playwright CDP è¿æ¥è¶
æ¶ Timeout 9000ms exceeded |
馿¬¡è¿æ¥éè¯ 5s/7s/9s ä¸å¤ï¼ARM ä¸ Chrome åå§åæ ¢ | ä¿®æ¹æºç 5e3 + attempt * 2e3 â 15e3 + attempt * 5e3ï¼è§ 8g èï¼ |
| 18 | éå¯åæµè§å¨æä½å¡æ»ï¼14 个æ ç¾æ¢å¤ï¼ | Chrome ä» user-data æ¢å¤æ§ä¼è¯æ ç¾ï¼å¤æ ç¾èå°½ CPU | éå¯åç¨ CDP API å ³éå¤ä½æ ç¾ï¼ææ¸ ç user-data |
| 19 | Google News çéå SPA å§ç»è¶ æ¶ | ARM + swiftshader 软件渲æï¼å¤æ JS/CSS 渲æè¶ è¿ 60 ç§ | ç¨è½»é级ç½ç«æ RSS/API æ¿ä»£ï¼æ æ³éè¿å¢å è¶ æ¶è§£å³ |
| 20 | Chrome è½è®¿é®å½å ç«ä½æ æ³è®¿é®æµ·å¤ç« | wrapper ä¸ unset äºä»£çåéï¼Chrome æ æ³ç´è¿æµ·å¤ | æå»ºæ¬å°ä»£çä¸ç»§ + --proxy-server=127.0.0.1:7891ï¼è§ 8b èï¼ |
| 21 | SSH ä¼ è¾ wrapper èæ¬ shebang åæ #\! |
zsh çå岿©å±æ ! è½¬ä¹æ \! |
ç¨ scp ä¼ è¾æä»¶ï¼æå¨è¿ç¨æå¡å¨ä¸ç´æ¥ç¼è¾ |
| 22 | X ç»å½é¡µæ¾ç¤º “Something went wrong” | ARM + swiftshader è½¯ä»¶æ¸²ææ æ³è¿è¡ X ç React SPA | ä¸è¦ç¨æµè§å¨èªå¨åç»å½ï¼ç´æ¥æ³¨å ¥ auth_token |
| 23 | Twitter API ç»å½è¿å error 399 “Could not log you in now” | 夿¬¡å¤±è´¥å°è¯è§¦å IP 级å«éé¢ | ä¸è¦åå¤éè¯ç»å½ APIï¼ä¸æ¦è¢«éé¢éçå¾ æ°å°æ¶ |
| 24 | Python twikit/httpx 被 Cloudflare 403 æ¦æª | Python HTTP 客æ·ç«¯ç TLS æçº¹ä¸æµè§å¨ä¸å | åªè½éè¿ç宿µè§å¨ï¼Chrome CDPï¼åèµ·è¯·æ± |
| 25 | Chrome fetch + credentials: 'include' æ¥ CORS é误 |
x.com å api.twitter.com 另忮çè·¨å请æ±è§¦å preflight 失败 | ç¨ CDP Fetch.enable å¨åè®®å±æ³¨å
¥ Cookie 头ç»è¿ CORS |
| 26 | document.cookie 读ä¸å° ct0 |
ct0 æ¯ httpOnly cookieï¼JS æ æè®¿é® | ç¨ CDP Network.getAllCookies ä»åè®®å±è¯»å |
| 27 | urllib.request.urlopen() ä¸èµ°ä»£ç |
urllib ç urlopen é»è®¤ä¸ä½¿ç¨ https_proxy ç¯å¢åé |
æ¾å¼å建 ProxyHandler + build_opener |
| 28 | env æä»¶ source æ¥ command not found |
å¯ç /token ä¸å« | çç¹æ®å符æªå å¼å·ï¼bash æ | åé¢å½å½ä»¤æ§è¡ |
env æä»¶ä¸ææå¼ç¨åå¼å·å 裹 |
| 29 | Chrome éå¯å X ç»å½ä¸¢å¤±ï¼auth_token 被åé | Network.setCookie ä¸å¸¦ expires åªåå
åï¼éå¯å丢失ï¼Twitter æ£æµ session æå¼ååé token |
注å
¥ cookie æ¶å¿
须带 expiresï¼1 å¹´ï¼ï¼ç»å½åååå
¨é¨ cookie ä¹å¸¦ expires |
| 30 | æå¡å¨ä¸ææèªå¨ç»å½æ¹æ¡å失败ï¼API/twikit/CDP Fetch/Chrome JS/CORSï¼ | ARM 软件渲æ + Cloudflare TLS æçº¹ + CORS éå¶ = æ æ³å¨æå¡å¨å®æç»å½ | æ¾å¼å¨æå¡å¨ç»å½ï¼è®©ç¨æ·å¨èªå·±çµèæµè§å¨è·å auth_token åæ³¨å ¥ |