Files
scraper/stalk_tiktok.py
T

64 lines
2.2 KiB
Python
Raw Normal View History

"""Extract TikTok user-detail JSON (__UNIVERSAL_DATA_FOR_REHYDRATION__) via Playwright.
The direct HTTP path gets a SlardarWAF challenge page; a real browser with JS
executes the challenge and exposes the __UNIVERSAL_DATA_FOR_REHYDRATION__ script.
Usage: python3 stalk_tiktok.py <username>
"""
import sys
import asyncio
import json
import os
os.environ.setdefault("PLAYWRIGHT_BROWSERS_PATH", "/usr/local/share/ms-playwright")
from playwright.async_api import async_playwright
async def main(username):
url = f"https://www.tiktok.com/@{username}?_t=ZS-8tHANz7ieoS&_r=1"
async with async_playwright() as p:
browser = await p.chromium.launch(
headless=True,
args=["--no-sandbox", "--disable-bypass", "--disable-blink-features=AutomationControlled"],
)
context = await browser.new_context(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
viewport={"width": 1366, "height": 768},
java_script_enabled=True,
locale="en-US",
)
page = await context.new_page()
try:
await page.goto(url, timeout=60000, wait_until="domcontentloaded")
except Exception as e:
await browser.close()
print(json.dumps({"success": False, "error": f"Navigation: {e}"}))
return
# Wait for the rehydration script to appear (WAF challenge may take a few seconds)
found = None
for _ in range(30):
try:
found = await page.evaluate(
"""() => {
const s = document.querySelector('script#__UNIVERSAL_DATA_FOR_REHYDRATION__');
return s ? s.textContent : null;
}"""
)
if found:
break
except Exception:
pass
await page.wait_for_timeout(1000)
await browser.close()
if not found:
print(json.dumps({"success": False, "error": "Rehydration data not found (WAF challenge)"}))
return
print(json.dumps({"success": True, "data": found}))
if __name__ == "__main__":
asyncio.run(main(sys.argv[1]))