# -*- coding: utf-8 -*- # Author : Charley # Python : 3.12.10 # Date : 2026/07/15 """ SCP Auctions (catalogs.scpauctions.com) 全量历史爬虫(一次性脚本) 逻辑(两阶段): 阶段一 列表:GET /auctions/past 翻页解析「全部」历史拍卖会 → 逐场入库 scp_auction, 再逐场翻页抓 lot 列表入库 scp_lot(state 默认 0) 阶段二 详情:扫库 scp_lot 中 state != 1 的记录 → 逐条进详情页抓 「标题 + 成交价 + 属性(Collection/Sport/Type/Athlete/Team) + 多图」写回 适用场景:初始化数据库时跑一次。后续每周增量由 scp_spider.py 负责。 """ import sys import random from curl_cffi import requests from loguru import logger from mysql_pool import MySQLConnectionPool from scp_core import ( client_identifier_list, crawl_one_auction, get_auction_list, save_auction, update_details_for_pending, ) logger.remove() logger.add("./logs/his_{time:YYYYMMDD}.log", encoding="utf-8", rotation="00:00", format="[{time:YYYY-MM-DD HH:mm:ss.SSS}] {level} {message}", level="DEBUG", retention="7 day") # —— 调试开关 —— # 只抓前 N 个拍卖会,None 表示全抓(生产);测试时设小一点,比如 1 DEBUG_AUCTION_LIMIT = None def run_history(log, sql_pool): """全量抓取所有历史拍卖会及其 lot 列表(阶段一)。 Args: log: logger 对象。 sql_pool: MySQL 连接池;传 None 时不入库,仅翻页抓取并 print 样本。 Returns: None: 结果直接入库,无返回值。 """ impersonate = random.choice(client_identifier_list) with requests.Session() as session: try: auctions = get_auction_list(log, session, impersonate, only_first_page=False) except Exception as e: log.error(f"获取拍卖会列表失败: {e}") return if DEBUG_AUCTION_LIMIT is not None: auctions = auctions[:DEBUG_AUCTION_LIMIT] log.warning(f"[DEBUG] 调试模式,仅抓前 {len(auctions)} 场拍卖会") for idx, auc in enumerate(auctions, 1): log.info(f"========== [{idx}/{len(auctions)}] 拍卖会 {auc['event_id']} ({auc['auction_name']}) ==========") try: save_auction(log, sql_pool, auc) # 先入库拍卖会本身 lots = crawl_one_auction(log, sql_pool, session, impersonate, auc) if sql_pool is None: for row in lots[:2]: print(row) except Exception as e: log.error(f"拍卖会 {auc['event_id']} 抓取异常: {e}") continue def scp_history_main(log): """全量历史抓取入口。 Args: log: logger 对象。 Returns: None: 无返回值。 """ log.info(f"开始运行 {sys._getframe().f_code.co_name} 全量爬虫任务 ...") sql_pool = MySQLConnectionPool(log=log) if not sql_pool: log.error("MySQL数据库连接失败") raise Exception("MySQL数据库连接失败") try: # 阶段一:抓拍卖会 + lot 列表入库 run_history(log, sql_pool) # 阶段二:扫库 state != 1 的 lot 补抓详情 update_details_for_pending(log, sql_pool) except Exception as e: log.error(f"{sys._getframe().f_code.co_name} error: {e}") finally: log.info(f"爬虫程序 {sys._getframe().f_code.co_name} 运行结束") if __name__ == "__main__": scp_history_main(log=logger)