在线浏览“秀人网合集”的新思路:30 行 Python 把封面图链接秒变本地可点图库

用 30 行 Python 把秀人网公开合集"搬"进本地数据库


"秀人网"近日上线的新主题合集页采用前端渲染,数据通过 /api/v2/theme/list 接口一次性返回 JSON,无需模拟点击"加载更多"。接口无登录限制,但带 5 秒滑动窗口的 IP 频次校验:单 IP >30 次/分即返回 429。本文示范如何遵守 robots 协议、放缓速率,仅采集"公开可见"字段,并给出断点续抓、User-Agent 随机化、异常重试等常用技巧。

核心思路三步走:

分析列表接口:在浏览器 DevTools 里筛选 XHR,发现真实请求 URL 形如

https://www.xiuren.net/api/v2/theme/list?page={page}\&size=20,返回体含 data.total 与 data.list。

解析单条记录:字段 title、author、coverUrl 即为我们需要的元数据,无需再进详情页。

限速+重试:用 tenacity 的 @retry(stop=stop_after_attempt(3)) 装饰器,遇到 429 自动退避 10 秒;全局速率 time.sleep(random.uniform(1, 2)),确保平均 <30 次/分。

运行环境:Python≥3.7,依赖如下

pip install requests pandas tenacity fake-useragent

代码(文件 save_xiuren_meta.py):

python 复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
抓取秀人网公开主题合集元信息,仅采集 title/author/coverUrl 三字段。
仅供学习,请遵守平台 robots.txt 与相关法律法规。
"""
import csv, time, random, requests
from tenacity import retry, stop_after_attempt, wait_fixed
from fake_useragent import UserAgent

BASE_URL = "https://www.xiuren.net/api/v2/theme/list"
CSV_FILE = "xiuren_meta.csv"
PAGE_SIZE = 20
MAX_PAGE = 50          # 按需调整,0 表示抓全量
SLEEP_RANGE = (1, 2)   # 秒,随机休眠

ua = UserAgent()
session = requests.Session()
session.headers.update({"Referer": "https://www.xiuren.net/"})

@retry(stop=stop_after_attempt(3), wait=wait_fixed(10))
def fetch_one_page(page: int):
    session.headers.update({"User-Agent": ua.random})
    params = {"page": page, "size": PAGE_SIZE}
    resp = session.get(BASE_URL, params=params, timeout=10)
    if resp.status_code == 429:
        raise Exception("Rate limited")
    resp.raise_for_status()
    return resp.json()

def main():
    writer = None
    for p in range(1, MAX_PAGE + 1):
        print(f"[+] 正在抓取第 {p} 页 ...")
        js = fetch_one_page(p)
        rows = [
            {"title": item["title"], "author": item["author"], "coverUrl": item["coverUrl"]}
            for item in js["data"]["list"]
        ]
        if not writer:
            writer = csv.DictWriter(open(CSV_FILE, "w", newline="", encoding="utf-8"),
                                    fieldnames=["title", "author", "coverUrl"])
            writer.writeheader()
        writer.writerows(rows)
        if js["data"]["total"] <= p * PAGE_SIZE:
            break
        time.sleep(random.uniform(*SLEEP_RANGE))
    print(f"[√] 抓取完成,已写入 {CSV_FILE}")

if __name__ == "__main__":
    main()

运行后同级目录生成 xiuren_meta.csv,可导入 Excel 或数据库二次分析。若需增量更新,可把 CSV_FILE 改为 SQLite,并在写入前按 title 做唯一索引去重。

再次提醒:

仅抓取"公开可见"字段,不绕过登录、不破解加密参数;

速率温和,不干扰站点正常服务;

数据勿商用,尊重原作者版权。

祝各位读者调试顺利,也欢迎把改进方案提交到开源社区,共同维护良好的技术交流氛围。

相关推荐
大风起兮云飞扬丶12 分钟前
Java——枚举
java·开发语言
小灰灰搞电子16 分钟前
Rust+Slint 实现高级动态消息提示框源码分享
开发语言·rust
Dev _19 分钟前
Python解释器安装在系统级目录导致命令行用户‌没有权限‌向该目录写入文件
开发语言·python
qq_4069810337 分钟前
大白话rust系列08 当变量遮蔽遇上引用,探究变量遮蔽的本质
开发语言·后端·rust
喵了几个咪1 小时前
GoWind ShortPlay 拆解:不用模型的推荐闭环——埋点回流、三路召回与已看去重
开发语言·后端·微服务·golang·gowind
谙弆悕博士1 小时前
用 C 写了个 Windows 聊天室,踩了几个多线程和控制台的坑
c语言·开发语言·c++·windows·网络编程·聊天室
Dev _1 小时前
PyCharm旧进程仍在后台运行,导致新实例无法启动或连接
ide·python·pycharm
Canmag 兴隆磁性1 小时前
回复磁导率 μ_R:永磁体在动态磁路中的关键参数
开发语言·学习·r语言·永磁材料·充磁·磁导率
CRMEB系统商城1 小时前
鲜花零售的预售与积分营销
开发语言·人工智能·科技·小程序·零售
Wang's Blog2 小时前
Java 项目实战: 交友项目 - 喜欢与取消喜欢
java·开发语言·交友