naughtyamerica.25.10.18

今天凌晨的某个时刻,我彻底征服了naughtyamerica🤔自从去年开始大规模拖sexart算起,我基本上已经一年多没有拖任何pornsite力(悲🤔naughtyamerica通常来说也不是我的首选项,因为在我的印象里这个站在某年(可能是23?)的改版后,下载任何一个视频都需要经过一番google验证🤔但由于某种申必原因,我六月还是哪个月买的naughtyamerica号居然还在,而czechcasting我又没买,所以我现在能拖的也就只有naughtyamerica🤔

照例打开f12视奸它的http协议流,在我对着它的视频页面的streaming preference点了下4k后,本来我以为它会像什么mofos之类的一样触发m3u8这样的流式传输,结果我发现它触发了一个完整视频文件的请求,它和(需要通过google验证后才出现的)下载链接居然长得完全一样,除了后面可能少一个&dl=1🤔如果下载该链接的话得到的文件也和下载链接至少在文件大小上完全一致(我就懒得验证它们checksum到底匹不匹配力),这说明它给streaming准备的文件至少不是劣化版🤔而且我在streaming preference里随便点,除了对应的视频文件外没有观测到任何别的xhr请求,这说明它所有的下载链接其实早就在某次请求中一次性获取力,至于这次请求在哪里,,,我甚至都没花多少时间排查,直接从第一个请求也就是html文件里就发现了所有版本的mp4视频🤔

既然如此,考虑到我有114514个各种ai的黑色高级会员,我就懒得自己去提取力,直接扔进ai里让它给个bash脚本出来,然后过滤掉我不想要的链接(比如那些带captcha的,这些很明显是理论上来说下载视频需要访问然后过google验证的),还有什么xml,剩下的链接我直接一个一个一个一个用aria2下就vans力(确信🤔

这里面我发现了一个一个一个彩蛋,它有个链接叫做https://members.naughtyamerica.com/playlist-generator.scene.33438.4k.mp4.xml,这里也能提取出一个视频链接出来,但它一次访问只能提取出一个,但我访问一次html就能提取出所有链接,所以这个彩蛋基本上没啥卵用

但接下来我遇到了另外一个一个一个一个困难,这b网站除了下载需要验证外,访问它其实也需要验证,而且无论是用原版curl还是各种魔改版curl都不好使🤔那么用吴头浏览器呢?其实也不好使,而且我用传统的聊天ai配置了十几次都没配置对🤔它这玩意貌似使用了aws的黑色高级waf,第一次请求可能不成功,然后它会触发一个challenger.js,跑完这玩意获取某申必代码后会请求第二次,此时才会给真正的html,所以只能死板访问某一个链接的吴头浏览器对付这种逆天玩意貌似比curl好不了多少(全恼🤔考虑到这个我从某申必渠道搞到的aws灵车vps居然有4GB的超大内存(对vps来说确实很大),我也许可以试试在vps上跑一个有头浏览器,比如chrome,然后开启它的调试模式,开放一个调试端口,然后在另外一个脚本里用这个端口打开我们要打开的页面并且输出html🤔从某种程度上说这甚至比用curl方便,因为除了将curl替换成操控浏览器的py脚本外,后面不用跟任何headers(确信🤔我只需要在那个有头浏览器上登录naughtyamerica一次,然后就可以不用管它力,除非它掉登录或者需要更严格的验证(确信🤔

而且更妙的是,这些东西完全不需要我自己来配置,因为现在有各种cli版本的ai agent,比如claude code和gpt codex🤔这玩意在桌面pc上怎么用怎么别扭(因为我cursor用得多),但在vps上就刚刚好(迫真🤔我刚好有这两者的api key,但cc由于某种申必原因用不了,所以我在那台vps上装了个codex,然后让它配置chrome和所谓的最小桌面系统🤔我甚至都没有提及xrdp,它也有可能装vnc server或者别的玩意(比如parsec?),但它还是装了xrdp,甚至配置成功力,我自己配置xrdp都没有配置成功过哪怕一次🤔

连上去后我按照它的说明启动了chrome,但一直没法远程调试,这里至少有两个坑,一个是root用户启动chrome要带--no-sandbox参数,另外一个是user-data-dir必须选择和默认值不一样的位置🤔我登上naughtyamerica之后让ai写了一个na.py,让它像curl一样只要后面跟上链接就能返回该链接的完整html内容,这样它就能自动完成任何验证,毕竟它跑在一个真实的有头浏览器上(确信🤔考虑到aws逆天waf的原理,它每次运行基本上五六秒才能吐出一串链接,我如果想再保存html的话就得再花五六秒(全恼🤔

我用这套玩意代替curl能吴缝跑完下载脚本,但接下来还有一个问题,如果我关掉rdp窗口后,chrome就会像没有screen的命令行窗口一样被橄榄,所以我让ai做了某种类型的持久化配置,它将chrome对应的命令行做成了系统服务,这样只要启动应该就能自动开启chrome,然后开放指定的端口🤔那么如果naughtyamerica掉登录力,该怎么办?很简单,连上rdp,然后在chrome里顶着卡顿重新登录一遍就vans力🤔那么该脚本就剩下了最后一步,将下载下来的东西上传guilded drive然后删掉本地文件,不然这个存储空间只有128GB的vps随便下几个片子就会爆🤔

如果我接下来还需要改进什么的话,可能需要给我的脚本加上队列功能,从而哪怕它在处理时我也可以给它加链接?或者整个数据库啥的保存已经处理的链接等?甚至整个web系统,免得我每次添加队列的时候都需要登vps🤔而且这些其实都可以让ai来写(确信🤔但也有可能在我有什么大规模拖naughtyamerica的计划前,我那台aws灵车vps很快就会因为哼哼雷普naughtyamerica而被橄榄,鬼知道🤔

但无论如何,这是我拖pornsite生涯中第一次几乎全程使用ai整的,感觉还行,甚至有点暗爽🤔

附录(大嘘

完整chrome启动命令

/usr/bin/google-chrome-stable --remote-debugging-port=9222 --remote-debugging-address=127.0.0.1 --remote-allow-origins=* --user-data-dir=/root/.config/google-chrome114514 --no-first-run --no-default-browser-check --no-sandbox

使用的提示词

  • “请为该系统配置一个能够启动chrome浏览器的最小环境,考虑到我没法访问该vps的vnc console,我还需要一种手段能够远程连接它的图形界面”
  • “接下来我需要启动chrome但让它可以开放一个端口供某自动化工具(比如playright)调用,我需要以什么参数启动?对应的自动化工具是否能够使用我的登录凭据?请设计某工具让它能够在该已经打开的浏览器里打开某指定页面,并返回完整html内容”
  • “请编写一个py程序,使得我在bash里面调用它,比如na.py https://members.naughtyamerica.com/scene/co-ed-nerd-jade-valentine-has-the-hots-for-her-college-professor-32869,它应该能够使用我已经打开并有那个网站登录凭据的浏览器打开该页面,并在标准输出里输出该页面的html内容”
  • “如何在我关掉rdp之后,chrome仍然保持运行?”
  • “请对root用户完成上述设置”
  • “我需要将chrome位置文件设置成$HOME/.config/google-chrome114514,请修改对应的项目”

na.py

#!/usr/bin/env python3
"""
Launches a new page inside an already running Chrome instance (started with a
remote debugging port) and prints the rendered HTML to stdout.

Example:
    ./na.py https://example.com
"""

from __future__ import annotations

import argparse
import json
import sys
import urllib.error
import urllib.request
from typing import Optional

from playwright.sync_api import sync_playwright


def fetch_ws_endpoint(debug_base_url: str) -> str:
    """Return the websocket debugger URL from the remote debugging endpoint."""
    with urllib.request.urlopen(f"{debug_base_url.rstrip('/')}/json/version", timeout=10) as resp:
        data = json.loads(resp.read().decode("utf-8"))
    ws_url = data.get("webSocketDebuggerUrl")
    if not ws_url:
        raise RuntimeError("webSocketDebuggerUrl not found in /json/version response")
    return ws_url


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(description="Fetch a page through an existing Chrome session.")
    parser.add_argument("url", help="Target page URL to load inside Chrome.")
    parser.add_argument(
        "--debug-url",
        default="http://127.0.0.1:9222",
        help="Base URL of Chrome's remote debugging endpoint (default: %(default)s).",
    )
    parser.add_argument(
        "--wait-until",
        default="networkidle",
        choices=["load", "domcontentloaded", "networkidle"],
        help="Event to wait for before dumping HTML (default: %(default)s).",
    )
    parser.add_argument(
        "--timeout",
        type=float,
        default=30000,
        help="Navigation timeout in milliseconds (default: %(default)s).",
    )
    return parser.parse_args()


def choose_context(browser) -> tuple:
    """
    Return (context, owned) where owned indicates whether the context was created
    by this function (and thus should be closed on exit).
    """
    contexts = browser.contexts
    if contexts:
        return contexts[0], False
    return browser.new_context(), True


def main() -> int:
    args = parse_args()

    try:
        ws_url = fetch_ws_endpoint(args.debug_url)
    except (urllib.error.URLError, RuntimeError, json.JSONDecodeError) as exc:
        print(f"Failed to obtain websocket debugger URL from {args.debug_url}: {exc}", file=sys.stderr)
        return 1

    with sync_playwright() as playwright:
        browser = playwright.chromium.connect_over_cdp(ws_url)

        context, owned = choose_context(browser)
        page = context.new_page()
        try:
            page.goto(args.url, wait_until=args.wait_until, timeout=args.timeout)
            html = page.content()
        finally:
            page.close()
            if owned:
                context.close()

        print(html)
    return 0


if __name__ == "__main__":
    try:
        sys.exit(main())
    except KeyboardInterrupt:
        sys.exit(130)

ai对此的迫真总结

这次在一台无法直接访问 VNC 控制台的 Ubuntu 22.04 VPS 上,我搭建了一个能远程使用 Chrome 浏览器的最小化图形环境,并且让自动化脚本能够复用浏览器的登录状态。首先刷新 apt 仓库,安装 xrdp 与 XFCE 轻量桌面,通过修改 /etc/xrdp/startwm.sh 让 RDP 登陆直接进入 XFCE;启动并启用 xrdp.service 后,安全组开放 TCP 3389,即可用任意 RDP 客户端连接。紧接着添加 Google 官方仓库并安装 google-chrome-stable。为了让自动化工具复用登录凭据,我用 Python 与 Playwright 编写了 na.py,脚本会连接已经开启远程调试端口的 Chrome,并在同一用户数据目录里新开标签页、加载目标网址、输出完整 HTML。最后,为了在断开 RDP 后保持浏览器运行,使用 root 用户的 systemd user 服务,将 Chrome 以 remote-debugging 模式后台常驻,数据目录换成 ~/.config/google-chrome114514,并开启 linger,这样自动化任务随时可以通过http://127.0.0.1:9222 附着到现成会话。整套流程解决了无图形控制台的远程浏览器需求,也兼顾了登录态复用与自动化。

一键脚本(迫真

有一种水字数的美,另外这个脚本我没测过,如果我这台鸡鸡暴毙的话我也许会去测?🤔

#!/usr/bin/env bash
# Sets up a minimal XFCE + XRDP environment with Chrome running in remote
# debugging mode for automation reuse. Intended to be run as root on a fresh
# Ubuntu 22.04 VPS.

set -euo pipefail

if [[ "{EUID}" -ne 0 ]]; then
  echo "This script must be run as root." >&2
  exit 1
fi

export DEBIAN_FRONTEND=noninteractive

echo "[*] Updating apt metadata..."
apt-get update

echo "[*] Installing desktop and RDP components..."
apt-get install -y \
  xrdp \
  xfce4 \
  xfce4-terminal \
  dbus-x11 \
  wget \
  gnupg \
  python3-pip

echo "[*] Ensuring XRDP launches XFCE sessions..."
cat <<'EOF' >/etc/xrdp/startwm.sh
#!/bin/sh

if test -r /etc/profile; then
    . /etc/profile
fi

if command -v startxfce4 >/dev/null 2>&1; then
    exec startxfce4
fi

test -x /etc/X11/Xsession && exec /etc/X11/Xsession
exec /bin/sh /etc/X11/Xsession
EOF
chmod +x /etc/xrdp/startwm.sh

echo "[*] Allowing XRDP to read system certificates..."
adduser xrdp ssl-cert || true

echo "[*] Enabling XRDP service..."
systemctl enable --now xrdp

echo "[*] Adding Google Chrome repository..."
install -d -m 0755 /usr/share/keyrings
wget -qO- https://dl.google.com/linux/linux_signing_key.pub \
  | gpg --dearmor >/usr/share/keyrings/google-linux-signing-keyring.gpg
cat <<'EOF' >/etc/apt/sources.list.d/google-chrome.list
deb [arch=amd64 signed-by=/usr/share/keyrings/google-linux-signing-keyring.gpg] https://dl.google.com/linux/chrome/deb/ stable main
EOF

echo "[*] Installing Google Chrome..."
apt-get update
apt-get install -y google-chrome-stable

CHROME_DATA_DIR="/root/.config/google-chrome114514"
echo "[*] Preparing Chrome data directory at{CHROME_DATA_DIR}..."
install -d -m 0700 "{CHROME_DATA_DIR}"

SYSTEMD_USER_DIR="/root/.config/systemd/user"
echo "[*] Creating Chrome systemd user service..."
install -d -m 0755 "{SYSTEMD_USER_DIR}"
cat <<'EOF' >"{SYSTEMD_USER_DIR}/chrome-remote.service"
[Unit]
Description=Chrome with remote debugging
After=default.target

[Service]
Environment=DISPLAY=:10
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%U/bus
Environment=XAUTHORITY=/root/.Xauthority
ExecStart=/usr/bin/google-chrome-stable --remote-debugging-port=9222 --remote-debugging-address=127.0.0.1 --remote-allow-origins=* --user-data-dir=/root/.config/google-chrome114514 --no-first-run --no-default-browser-check --no-sandbox
Restart=on-failure

[Install]
WantedBy=default.target
EOF

echo "[*] Enabling linger for root so the user service remains after logout..."
loginctl enable-linger root || true

export XDG_RUNTIME_DIR="/run/user/0"
if [[ ! -d "{XDG_RUNTIME_DIR}" ]]; then
  echo "[*] Creating XDG runtime directory at {XDG_RUNTIME_DIR}..."
  install -d -m 0700 "{XDG_RUNTIME_DIR}"
fi

echo "[*] Reloading user systemd daemon and starting Chrome service..."
XDG_RUNTIME_DIR=/run/user/0 systemctl --user daemon-reload
XDG_RUNTIME_DIR=/run/user/0 systemctl --user enable --now chrome-remote.service

echo "[*] Installing Python Playwright package for automation helper..."
python3 -m pip install --upgrade pip
python3 -m pip install playwright

echo "[*] Deploying na.py helper script..."
cat <<'EOF' >/root/na.py
#!/usr/bin/env python3
"""
Attach to an existing Chrome instance (started with --remote-debugging-port),
open a given URL, and print the rendered HTML to stdout.
"""

from __future__ import annotations

import argparse
import json
import sys
import urllib.error
import urllib.request

from playwright.sync_api import sync_playwright


def fetch_ws_endpoint(debug_base_url: str) -> str:
    with urllib.request.urlopen(f"{debug_base_url.rstrip('/')}/json/version", timeout=10) as resp:
        data = json.loads(resp.read().decode("utf-8"))
    ws_url = data.get("webSocketDebuggerUrl")
    if not ws_url:
        raise RuntimeError("webSocketDebuggerUrl not found in /json/version response")
    return ws_url


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(description="Fetch a page through an existing Chrome session.")
    parser.add_argument("url", help="Target page URL to load inside Chrome.")
    parser.add_argument(
        "--debug-url",
        default="http://127.0.0.1:9222",
        help="Base URL of Chrome's remote debugging endpoint (default: %(default)s).",
    )
    parser.add_argument(
        "--wait-until",
        default="networkidle",
        choices=["load", "domcontentloaded", "networkidle"],
        help="Event to wait for before dumping HTML (default: %(default)s).",
    )
    parser.add_argument(
        "--timeout",
        type=float,
        default=30000,
        help="Navigation timeout in milliseconds (default: %(default)s).",
    )
    return parser.parse_args()


def choose_context(browser):
    contexts = browser.contexts
    if contexts:
        return contexts[0], False
    return browser.new_context(), True


def main() -> int:
    args = parse_args()

    try:
        ws_url = fetch_ws_endpoint(args.debug_url)
    except (urllib.error.URLError, RuntimeError, json.JSONDecodeError) as exc:
        print(f"Failed to obtain websocket debugger URL from {args.debug_url}: {exc}", file=sys.stderr)
        return 1

    with sync_playwright() as playwright:
        browser = playwright.chromium.connect_over_cdp(ws_url)

        context, owned = choose_context(browser)
        page = context.new_page()
        try:
            page.goto(args.url, wait_until=args.wait_until, timeout=args.timeout)
            html = page.content()
        finally:
            page.close()
            if owned:
                context.close()

        print(html)
    return 0


if __name__ == "__main__":
    try:
        sys.exit(main())
    except KeyboardInterrupt:
        sys.exit(130)
EOF
chmod +x /root/na.py

echo
echo "Setup complete."
echo "Summary:"
echo "  - XRDP is running on TCP 3389 with XFCE desktop."
echo "  - Chrome runs headless via systemd user service using profile ${CHROME_DATA_DIR}."
echo "  - Remote debugging available on 127.0.0.1:9222 (tunnel or firewall accordingly)."
echo "  - Use /root/na.py <URL> to open pages in the logged-in Chrome session and dump HTML."
echo
echo "Reminder: allow TCP 3389 in your VPS firewall/security group and tunnel port 9222 securely."

这是ai写的使用说明:

Script Details

  • Added setup_chrome_xrdp.sh to automate the entire environment setup for another VPS (setup_chrome_xrdp.sh:1). It installs XRDP + XFCE, configures /etc/xrdp/startwm.sh, adds the Google Chrome repo, installs Chrome, creates /root/.config/google-chrome114514, and deploys a root user systemd service that keeps Chrome running with remote debugging even after RDP disconnects. The script also installs Playwright and drops the reusable na.py helper (setup_chrome_xrdp.sh:82, /root/na.py:1).

How to Use

  • On the new VPS, copy the script and run bash setup_chrome_xrdp.sh as root. Wait for the “Setup complete.” message.
  • Open port 3389 in the server firewall/security group for RDP; keep 9222 restricted (e.g., SSH tunnel) since it exposes your Chrome session.
  • Connect via RDP, log in, and either browse manually or run ./na.py to fetch a page’s HTML through the already-authenticated Chrome instance.
  • Chrome now runs persistently via systemctl --user status chrome-remote (XDG_RUNTIME_DIR=/run/user/0 when checking from root).

Next Steps

  1. On the target VPS, execute the script and verify curl http://127.0.0.1:9222/json/version returns a WebSocket URL.
  2. If you need a different display number or profile path, edit the service in ~/.config/systemd/user/chrome-remote.service before re-running systemctl --user daemon-reload && systemctl --user restart chrome-remote.

发表评论