prezis/scraperx

GitHub: prezis/scraperx

一个无需 API 密钥的通用社交媒体与视频抓取工具,专注于真实性验证、冒充检测与跨平台视频发现。

Stars: 1 | Forks: 0

# ScraperX **通用抓取 + 视频智能分析,无需 API 密钥。** [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/6be7f35dbc152548.svg)](https://github.com/prezis/scraperx/actions/workflows/ci.yml) [![Version](https://img.shields.io/badge/version-1.3.0-informational.svg)](CHANGELOG.md) ScraperX 抓取社交媒体帖子、转录视频并验证真实性——无需 API 密钥或账户凭证。基于标准库,提供可选的感知图像哈希、网页抓取辅助和 GPU 加速语音转文本功能。 ## 功能 - **X / Twitter** — 推文、线程、资料、搜索。备用链(FxTwitter → vxTwitter → yt-dlp → oEmbed)在任一端点失效时保持数据流动。 - **YouTube 转录** — 自动字幕,支持 `faster-whisper`(GPU)或 `whisper`(CLI)作为回退。 - **Vimeo 转录**(1.3.0 新功能)— `oembed` + 播放器配置 + 创作者上传的 VTT 轨道,回退至 yt-dlp + whisper。 - **视频发现**(新增)— 在任意网页中扫描 6 个提供商(YouTube、Vimeo、Wistia、JWPlayer、Brightcove、HTML5)嵌入的视频。 - **线程真实性验证**(新增)— 对重构线程进行 4 属性形式化检查:`same_conversation`、`single_author`(数值 ID)、`chronological`、`no_interpolation`。 - **冒充检测**(新增)— 使用 pHash 8×8(64 位 DCT 感知哈希)的头像匹配器,配合 SQLite 缓存与滚动窗口注册表。捕捉盗用受害者头像并使用山寨账号的骗子。 - **诈骗内容检测** — 加密货币赠品短语、钱包地址、短链接域名、表情符号垃圾信息。 - **Token 提取** — `$CASHTAG` 提及与已知 Solana 代币。 - **SQLite 持久化** — 推文、资料、提及、头像哈希、搜索缓存。 为何不需要 API 密钥?官方 API 昂贵、限流且不稳定。ScraperX 依赖公共端点(oEmbed、FxTwitter、vxTwitter、syndication、yt-dlp),无需认证壁垒。 ## 安装 ``` pip install git+https://github.com/prezis/scraperx.git ``` 尚未在 PyPI 上提供;通过 GitHub 安装。 或克隆并以可编辑模式安装: ``` git clone https://github.com/prezis/scraperx.git cd scraperx pip install -e . ``` ### 可选扩展 | 扩展 | 安装内容 | 功能 | |---|---|---| | `[vision]` | `imagehash>=4.3`, `Pillow>=10.0` | 感知哈希头像匹配(缺失时回退至 SHA256) | | `[video-discovery]` | `beautifulsoup4>=4.12` | 更健壮的 HTML 解析,用于 `discover_videos` | | `[whisper]` | `faster-whisper>=1.0` | GPU 加速转录(比 openai-whisper 在 CPU 上快 4 倍) | | `[twscrape]` | `twscrape>=0.12` | 可选的账户支持 twscrape 后端 | 组合安装: ``` pip install "scraperx[vision,video-discovery,whisper] @ git+https://github.com/prezis/scraperx.git" ``` 系统工具(可选):`yt-dlp` 用于 Vimeo/Whisper 路径的音频下载;`whisper` CLI 作为 `faster-whisper` 未安装时的回退。 ## 快速开始 ### CLI ``` scraperx https://x.com/user/status/123456789 # scrape a tweet scraperx https://x.com/user/status/123 --thread # full thread scraperx @elonmusk # profile scraperx search "Meteora DLMM" --limit 10 # search (DDG + FxTwitter) scraperx https://youtube.com/watch?v=dQw4w9WgXcQ # YouTube transcript scraperx https://vimeo.com/76979871 # Vimeo transcript scraperx discover https://some-company.com/tour # find embedded videos ``` ### Python ``` from scraperx import XScraper, VimeoScraper, discover_videos, check_thread_authenticity scraper = XScraper() tweet = scraper.get_tweet("https://x.com/user/status/1234567890") print(f"{tweet.author_handle}: {tweet.text}") print(f" reply={tweet.is_reply} quote={tweet.is_quote}") print(f" author verified={tweet.author_verified} ({tweet.author_verified_type})") print(f" joined={tweet.author_joined} followers={tweet.author_followers}") vimeo = VimeoScraper() result = vimeo.get_transcript("https://vimeo.com/76979871") print(result.transcript[:500]) refs = discover_videos("https://some-blog.example.com/post") for v in refs: print(f"{v.provider}: {v.canonical_url}") ``` ## 架构 ``` URL or @handle or query │ ▼ ┌───────────────────────────┐ │ __main__.py CLI router │ └───────────────────────────┘ ┌────────┬─────────┬─────────┬─────────┬──────────┬──────────┐ ▼ ▼ ▼ ▼ ▼ ▼ ▼ Tweet Profile Thread YouTube Vimeo Discover Search │ │ │ │ │ │ │ scraper.py profile thread.py yt_sc.. vimeo_sc.. disco... search.py │ │ │ │ │ │ │ Fallback Fx+synd walk up captions oEmbed + regex+bs4 DDG+Fx chain timeline (Fx) + → whisper config scan enrich ┌──────┐ walk JSON │ Fx │ down │ │ vx │ (synd+DDG) ▼ │yt-dlp│ text_tracks │oembed│ → whisper └──────┘ \ │ / \ / │ ▼ ▼ ▼ ▼ ▼ │ ┌────────────────────────────┐ │ │ impersonation.py │ │ │ • handle typosquat │ │ │ • scam content regex │ │ │ • AvatarMatcher (pHash) │ │ │ • VerifiedAvatarRegistry │ │ └────────────────────────────┘ │ │ │ ▼ │ ┌──────────────────┐ │ │ authenticity.py │ │ │ 4-property check│ │ └──────────────────┘ │ │ │ ▼ ▼ ┌──────────────────────────────────┐ │ social_db.py (SQLite) │ │ tweets · profiles · mentions │ │ avatar_hash · verified_avatars │ └──────────────────────────────────┘ ``` ## 功能指南 ### 1. 推文抓取 — 1.3.0 的 21 个新字段 ``` from scraperx import XScraper scraper = XScraper() t = scraper.get_tweet("https://x.com/user/status/123") # Core (existed pre-1.3.0) t.id, t.text, t.author_handle, t.likes, t.retweets, t.views, t.media_urls, t.quoted_tweet # NEW — reply/quote/thread context t.is_reply, t.in_reply_to_tweet_id, t.in_reply_to_handle, t.in_reply_to_author_id t.is_quote, t.conversation_id # NEW — temporal + locale t.created_at, t.created_timestamp, t.lang, t.possibly_sensitive, t.source_client # NEW — community/note flags t.is_note_tweet, t.is_community_note_marked # NEW — author trust signals t.author_verified, t.author_verified_type # "blue" | "business" | "government" t.author_affiliation # org-linked badge dict t.author_followers, t.author_following t.author_joined # RFC 2822 — account age, strong scam signal t.author_protected, t.is_pinned ``` 全部向后兼容 — 每个新字段都有安全默认值。 ### 2. 线程重构 + 真实性验证 ``` from scraperx import get_thread, check_thread_authenticity thread = get_thread("https://x.com/user/status/123456") for t in thread.all_tweets: print(t.text) auth = check_thread_authenticity(thread) print(f"Authentic: {auth.is_authentic}") print(f" same conversation: {auth.same_conversation}") print(f" single author: {auth.single_author}") print(f" chronological: {auth.chronological}") print(f" no interpolation: {auth.no_interpolation}") if auth.reasons: for r in auth.reasons: print(f" ↳ {r}") ``` **形式化真实性属性:** 1. `same_conversation` — 所有推文共享根推文的 `conversation_id` 2. `single_author` — 所有推文共享根推文的数值 `author_id`(句柄可变;ID 不可变) 3. `chronological` — `created_timestamp` 在回复链中非递减 4. `no_interpolation` — 每个 `in_reply_to_tweet_id` 均在线程集合内解析 **建议标志:** `has_branches`(作者对同一父推文回复两次 — 路径而非树)、`root_deleted`(设置了 conversation_id 但根内容缺失)。 **优雅降级**:当 API 省略字段时:`missing_fields` 告知原因,检查器回退(缺失数值 ID 时使用 `author_handle`;缺失时间戳时使用推文 ID 排序)。 ### 3. 冒充检测 — 感知头像哈希 骗子复制已验证账户的头像并重新上传 — URL 不同但像素相同。URL 字符串比较毫无用处。`AvatarMatcher` 使用 pHash 8×8(通过 DCT 生成的 64 位感知哈希)与汉明距离阈值。 ``` from scraperx import AvatarMatcher, VerifiedAvatarRegistry matcher = AvatarMatcher() registry = VerifiedAvatarRegistry() # Seed the registry with known-good avatars registry.record_avatar("elonmusk", "https://pbs.twimg.com/profile_images/...", matcher) # A reply from @elonmuskk (typosquat) claiming to be Elon is_match, hamming, matched = registry.check_impersonation( claimed_handle="elonmuskk", avatar_url="https://pbs.twimg.com/profile_images/NEW_URL.jpg", matcher=matcher, ) if not is_match and matched and matched != "elonmuskk": print(f"IMPERSONATION: @elonmuskk sporting @{matched}'s avatar (hamming={hamming})") ``` **汉明阈值(64 位 pHash):** | 距离 | 解释 | |---|---| | ≤ 6 位 | 几乎确定是同一图像(重新上传 + 轻度 JPEG) | | 7–12 位 | 同一图像被修改(边框/覆盖/色调)— **标记** | | 13–20 位 | 模糊,需权衡 | | > 20 位 | 不同图像 | 默认阈值 `10`。哈希缓存在 SQLite 中,TTL 为 30 天。每句柄滚动窗口保留 5 个哈希以容忍故意的头像变更。 **安全性:** 主机允许列表(`pbs.twimg.com`)、2MB 大小上限、`image/*` 内容类型检查 — 防止 SSRF。 **无 `[vision]` 扩展时:** 降级为内容 SHA256 比较(仅字节级相同)。完全可选。 ### 4. YouTube + Vimeo 转录 ``` from scraperx import VimeoScraper from scraperx.youtube_scraper import YouTubeScraper # YouTube yt = YouTubeScraper() res = yt.get_transcript("https://youtube.com/watch?v=dQw4w9WgXcQ") print(res.transcript[:500]) # Vimeo vm = VimeoScraper() res = vm.get_transcript("https://vimeo.com/76979871") print(f"{res.title} / {res.author} / {res.duration_seconds}s") print(f"method: {res.transcript_method}") # text_tracks | whisper_faster | whisper_cli print(res.transcript[:500]) # Embed-domain-locked Vimeo — pass the embedder URL as referer res = vm.get_transcript( "https://player.vimeo.com/video/123456", referer="https://some-company.com/product-tour", ) ``` 转录优先级:创作者上传的 VTT → `faster-whisper`(GPU)→ `whisper` CLI。自动检测 GPU(CUDA 上使用 float16,Metal 上使用 int8,CPU 回退)。 ### 5. 视频发现 — 扫描任意网页 ``` from scraperx import discover_videos, fetch_any_video_transcript refs = discover_videos("https://some-company.example.com/product") for v in refs: print(f"{v.provider}: {v.canonical_url} (embed: {v.embed_url})") # Top-level dispatcher — direct URL or webpage, auto-routes result = fetch_any_video_transcript("https://some-blog.com/post-with-vimeo-embed") ``` **检测 6 个提供商模式:** - YouTube / youtube-nocookie iframe - Vimeo iframe(包括带哈希的未列出链接 `?h=abc`) - Wistia iframe 与 JS 嵌入(`
`) - JWPlayer(`cdn.jwplayer.com/players/...`) - Brightcove(`players.brightcove.net/{acc}/{player}/index.html?videoId={id}`) - HTML5 `
标签:Faster-Whisper, OEmbed, pHash, Python标准库, SEO, Solana, Splunk, SQLite缓存, Token提取, Vimeo抓取, Whisper, X Twitter抓取, YouTube抓取, ytt-dlp, 加密货币诈骗检测, 反冒充检测, 开源, 感知哈希, 文本摘要, 无API密钥, 短链接检测, 社交媒体抓取, 离线抓取, 线程真实性验证, 网页嵌入视频检测, 自动字幕, 表情符号垃圾检测, 视频抓取, 视频转录, 语音转文本, 逆向工具, 通用视频发现, 钱包地址检测, 防伪检测