ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python工业级爬虫框架:Amazon与Confluence增量采集实战

Python工业级爬虫框架:Amazon与Confluence增量采集实战 简介本资源是一套面向Python中级开发者与数据采集实践者的多场景网络爬虫项目代码包聚焦Amazon商品数据与Confluence企业知识库等典型目标站点解决动态渲染、登录鉴权、反爬绕过及结构化存储等实战难点。压缩包共41个文件含31个核心Python脚本涵盖spider_v1.0、confluence、amazonsims等模块、3个配置文件.cfg用于Scrapy工程管理、3个Markdown文档含README与help说明、2个JSON配置proxy与agents辅以.gitignore等开发支持文件整体仅47KB轻量易读且模块划分清晰。已有459人学习下载项目采用分站点独立实现通用工具封装如proxy、middlewares、common模块的设计思路提供可直接调试的请求封装、会话维持、User-Agent轮换、基础异常处理及CSV/JSON双格式输出能力是理解真实业务爬虫工程组织与落地细节的优质参考样本。1. 这不是“一键爬取亚马逊Confluence”的万能脚本而是一套需要你亲手校准的工业级数据采集框架你搜到这个python 爬虫(amazon, confluence ...)-spider.zip文件时大概率正卡在某个具体业务场景里可能是市场部要批量抓取竞品在 Amazon 上的实时价格与评论情感倾向也可能是内部知识管理团队想把 Confluence 里散落的项目文档自动归档到本地知识库还可能是运维同事需要定期拉取 Confluence 的页面变更历史做审计追踪。它不是那种点开就跑、跑完就出 Excel 的玩具脚本——压缩包里没有 GUI 界面没有“开始采集”按钮更没有预装好的 ChromeDriver。它是一套骨架一套用 Python 搭建的、带明确分工的爬虫工程结构核心价值在于“可维护性”和“可扩展性”。我见过太多人解压后直接双击main.py看到报错ModuleNotFoundError: No module named confluence就放弃其实问题根本不在代码而在你没理解它设计的底层逻辑它把“请求调度”、“响应解析”、“数据存储”、“反爬对抗”这四层完全解耦。比如 Amazon 部分默认用requests BeautifulSoup做轻量级静态页抓取但如果你要抓商品详情页里的动态加载价格它预留了selenium的接入接口Confluence 部分则强制要求你填入base_url和personal_access_token因为 Atlassian 从 2021 年起已全面禁用 Basic Auth硬编码密码会直接 401。关键词里反复出现的“批量型”“增量型”“垂直型”恰恰是这个框架真正发力的地方——它的scheduler.py不是简单循环而是内置了 SQLite 的增量指纹库每次抓取前先查数据库里有没有相同 URL 的last_modified时间戳有且时间未变就跳过这才是企业级爬虫和学生作业的本质区别。适合谁不是刚学完print(Hello World)的新手而是已经写过 3 个以上真实爬虫项目、被反爬封过 IP、被 Confluence 权限坑过、知道robots.txt不是法律条文而是工程师间的君子协定的人。2. 项目整体架构与设计逻辑为什么必须拆成 spider、parser、storage 三个模块2.1 模块化不是为了炫技而是为了解决“改一处崩全局”的运维噩梦我接手过一个客户项目他们原来的爬虫是单文件 800 行的amazon_scraper.py需求是“加个功能把抓到的评论按星级分类存进 MongoDB”。开发小哥花了两天改完测试通过上线后第三天凌晨报警Amazon 商品页结构微调div.product-price变成了span.a-price-whole整个脚本解析失败所有下游报表断更。问题根源在哪不是 XPath 写错了而是价格提取、评论提取、图片链接提取全挤在一个函数里改评论逻辑时手抖删了价格提取的 try-except 块。这个spider.zip的核心设计哲学就是用物理隔离杜绝逻辑污染。打开解压后的目录你会看到清晰的三层spider/ ├── core/ # 调度中枢不碰业务逻辑 │ ├── scheduler.py # 控制抓取节奏、去重、失败重试 │ └── session_manager.py # 统一管理 requests.Session 和 headers ├── spiders/ # 业务入口只负责“发请求” │ ├── amazon_spider.py # 构造 URL、设置 cookies、发起 GET │ └── confluence_spider.py # 处理 OAuth2 token、构造 REST API 请求头 ├── parsers/ # 解析工厂只负责“从 HTML/API 响应里抠数据” │ ├── amazon_parser.py # 用 CSS 选择器定位 price、review_count │ └── confluence_parser.py # 解析 JSON 响应里的 body.view.value 字段 └── storage/ # 数据出口只负责“存到哪、怎么存” ├── local_storage.py # 保存为 CSV/JSON 文件 └── database_storage.py # 插入 PostgreSQL 表含 UPSERT 逻辑提示spiders/目录下没有run_all.py。启动方式是python -m core.scheduler --target amazon --mode incremental参数--mode决定是全量抓取还是只抓新增页面。这种 CLI 设计强迫你思考“这次抓取的目标是什么”而不是无脑运行。2.2 Amazon 与 Confluence 的本质差异决定了它们绝不能共用同一套解析器新手常犯的错误是以为“都是网页用同一个 BeautifulSoup 解析就行”。但 Amazon 是典型的前端渲染型电商站关键数据如实时库存、促销倒计时藏在 JavaScript 变量里HTML 源码里只有占位符而 Confluence 是REST API 驱动的 Wiki 系统所有页面内容都可通过/rest/api/content/{id}?expandbody.view接口以 JSON 格式获取根本不需要解析 HTML。这个框架的高明之处在于用抽象基类BaseSpider强制规范了两者的差异# core/base_spider.py class BaseSpider(ABC): abstractmethod def build_request(self) - Request: # 子类必须实现如何构造请求 pass abstractmethod def parse_response(self, response: Response) - dict: # 子类必须实现如何解析响应 pass # spiders/amazon_spider.py class AmazonSpider(BaseSpider): def build_request(self): # 构造带 User-Agent 和 cookies 的 requests.Request return Request( urlfhttps://www.amazon.com/dp/{self.asin}, headers{User-Agent: Mozilla/5.0...}, cookiesself._load_amazon_cookies() # 从本地文件读取登录态 ) def parse_response(self, response): # 用 BeautifulSoup 解析 HTML再用正则从 script 标签里抠 JS 变量 soup BeautifulSoup(response.text, html.parser) price_script soup.find(script, stringre.compile(rpriceData)) price re.search(ramount:(\d\.\d), price_script.string).group(1) return {price: float(price), title: soup.title.text} # spiders/confluence_spider.py class ConfluenceSpider(BaseSpider): def build_request(self): # 构造带 Bearer Token 的 requests.Request return Request( urlf{self.base_url}/rest/api/content/{self.page_id}, headers{Authorization: fBearer {self.token}} ) def parse_response(self, response): # 直接解析 JSON提取富文本内容 data response.json() html_content data[body][view][value] # 清洗 HTML 标签保留段落结构 clean_text re.sub(r[^], , html_content) return {title: data[title], content: clean_text}这种设计让 Amazon 抓取可以随时切换成 Selenium只需重写build_request返回 WebDriver 实例而 Confluence 部分永远保持轻量——因为它的 API 响应稳定不需要模拟点击。你不会在parsers/目录下找到common_parser.py因为“通用解析器”在真实业务中根本不存在强行合并只会让代码变成意大利面条。2.3 “增量型”不是加个时间戳字段而是要解决数据一致性这个魔鬼细节热搜词里反复出现的“(1)批量型 (2)增量型 (3)垂直型”很多人只记住了名词却忽略了增量型爬虫真正的技术门槛如何定义“增量”是按页面最后更新时间按 URL 变更还是按内容哈希值这个框架选择了最稳妥的方案——基于 Confluence 页面的 version 字段 Amazon 商品的 last_updated 时间戳。但难点在于Confluence 的version是整数递增而 Amazon 商品页根本没有公开的 last_updated 字段。解决方案是parsers/amazon_parser.py里的一段硬核逻辑def extract_last_updated(soup: BeautifulSoup) - datetime: # 方案1找页面底部的“Last updated on”文字部分卖家页有 updated_text soup.find(stringre.compile(rLast updated.*\d{4})) if updated_text: return parse_date(updated_text) # 方案2解析页面内隐藏的 meta propertyarticle:modified_time 标签 meta_tag soup.find(meta, attrs{property: article:modified_time}) if meta_tag and meta_tag.get(content): return datetime.fromisoformat(meta_tag[content].replace(Z, 00:00)) # 方案3兜底方案——用当前时间减去商品上架天数从“Date First Available”推算 first_available soup.find(stringre.compile(rDate First Available)) if first_available: days_on_sale int(re.search(r(\d) days, first_available).group(1)) return datetime.now() - timedelta(daysdays_on_sale) return datetime.now() # 实在找不到用当前时间标记为需人工复核这段代码的价值不在于它多优雅而在于它承认了现实Amazon 的数据结构是混沌的。你不能指望所有页面都有标准字段必须准备至少 3 套 fallback 方案。而scheduler.py的增量逻辑正是基于这个extract_last_updated返回的时间与数据库里该 URL 的last_crawled_at做对比——只有当新时间 旧时间才触发解析和存储。这比简单的“URL 去重”严谨得多因为同一个 URL 的内容可能每天都在变。3. 核心细节解析与实操要点从解压到首次成功运行的完整链路3.1 环境准备为什么 pip install -r requirements.txt 会失败三个致命陷阱解压spider.zip后第一步必然是pip install -r requirements.txt。但几乎所有人都会在这里卡住原因不是网络问题而是三个被忽略的细节陷阱一Confluence 客户端库版本冲突requirements.txt里写着atlassian-python-api3.39.3这是经过验证的兼容版本。但如果你系统里已安装atlassian-python-api4.xpip install会静默升级导致confluence_spider.py报错AttributeError: Confluence object has no attribute get_page_by_id。因为 4.x 版本把方法名改成了get_page()。解决方案不是降级而是用虚拟环境彻底隔离# 推荐用 venv 创建纯净环境不要用 conda它会干扰系统 Python python -m venv spider_env source spider_env/bin/activate # Linux/Mac # spider_env\Scripts\activate.bat # Windows pip install --upgrade pip pip install -r requirements.txt陷阱二Amazon cookies 的获取方式不是“登录后复制”spiders/amazon_spider.py里有一行cookies self._load_amazon_cookies()它读取的是config/amazon_cookies.json。这个文件不能手动填写因为 Amazon 的 cookies 是动态生成的包含session-id、session-id-time、ubid-main等 10 个字段且session-id-time是 Unix 时间戳过期后整个 cookies 失效。正确做法是用框架自带的tools/cookie_extractor.py# 在 Chrome 浏览器中登录 Amazon 后运行 python tools/cookie_extractor.py --domain amazon.com --output config/amazon_cookies.json这个脚本会自动打开 Chrome DevTools 的 Application Cookies 面板读取当前 tab 的所有 cookies 并序列化。注意必须用 ChromeFirefox 的 cookies 格式不同且必须在登录状态下运行否则抓到的只是游客 cookies无法访问会员价。陷阱三Confluence 的 Personal Access Token 不是“API Key”config/confluence_config.yaml里要求填personal_access_token但很多人去 Confluence 后台找“API Keys”发现没有这个选项。这是因为 Atlassian 在 2022 年已弃用 API Keys改用Personal Access Tokens (PAT)。生成路径是右上角头像 Profile Manage Account Personal Access Tokens Create token。关键点Token 名称必须包含spider字样框架会校验权限必须勾选Read:Confluence Content和Read:Confluence Space复制后立即保存——页面关闭后无法再次查看注意confluence_config.yaml中的base_url必须是https://your-domain.atlassian.net/wiki结尾的/wiki不能省略否则 API 请求会返回 404。我见过三次因少写/wiki导致调试 6 小时的案例。3.2 配置文件详解yaml 里藏着 7 个影响成败的开关参数config/目录下有settings.yaml、amazon_config.yaml、confluence_config.yaml三个文件。新手常以为改amazon_config.yaml就够了其实settings.yaml才是总控开关# config/settings.yaml global: # 1. 并发控制不是越大越好Amazon 会封 IPConfluence 有 API 速率限制 max_concurrent_requests: 3 # Amazon 建议 ≤3Confluence 建议 ≤5 # 2. 请求间隔单位秒避免被识别为机器人 min_request_interval: 1.5 # Amazon 至少 1.5 秒Confluence 至少 0.5 秒 # 3. 失败重试策略指数退避防止雪崩 retry_strategy: max_retries: 3 backoff_factor: 2 # 第一次重试等 1.5s第二次等 3s第三次等 6s # 4. 数据存储路径绝对路径相对路径在 cron 任务中会失效 output_dir: /home/user/spider_output # Linux 示例Windows 用 C:\\spider_output # 5. 日志级别DEBUG 会打印每个请求的 headersINFO 只记录关键事件 log_level: INFO # 6. 增量模式开关true只抓新内容false全量重抓慎用 incremental_mode: true # 7. 反爬伪装开关true启用随机 User-Agent 和 Refererfalse用固定 UA enable_anti_anti_crawler: true其中enable_anti_anti_crawler: true是最易被忽视的参数。当它开启时core/session_manager.py会从内置的 UA 池中随机选取一个并设置Referer: https://www.google.com/。但如果你抓取的是 Confluence 内部页面Referer设成 Google 会导致 403 Forbidden——因为 Confluence 的 CSRF 保护会校验 Referer 是否来自自身域名。此时必须关掉此开关并在confluence_config.yaml中显式指定# config/confluence_config.yaml confluence: base_url: https://your-company.atlassian.net/wiki personal_access_token: your-token-here # 关键为 Confluence 设置专用 Referer referer: https://your-company.atlassian.net/wiki/pages/viewpage.action3.3 实操流程从配置到数据落地的 5 个不可跳过的步骤步骤 1初始化数据库SQLite并创建表结构框架默认使用 SQLite 存储增量指纹无需额外安装数据库。但必须手动执行初始化# 进入项目根目录 cd spider/ python -m core.db_init这个命令会创建data/crawl_fingerprints.db并建表CREATE TABLE IF NOT EXISTS fingerprints ( id INTEGER PRIMARY KEY AUTOINCREMENT, url TEXT UNIQUE NOT NULL, last_modified TEXT, -- ISO 格式时间戳如 2023-10-15T14:22:3300:00 content_hash TEXT, -- 内容 MD5用于检测页面是否真有变化 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );提示content_hash字段是防误判的关键。有些页面 HTML 结构不变但 JavaScript 渲染的内容变了比如价格浮动仅靠last_modified会漏抓。框架会在parsers/解析后计算hashlib.md5(content.encode()).hexdigest()存入此字段。步骤 2验证 Amazon cookies 是否有效别急着跑全量先用最小单元测试python -m spiders.amazon_spider --asin B08N5WRWNW --test-only--test-only参数会让脚本只执行build_request和parse_response不走存储流程。成功输出类似[INFO] AmazonSpider: Requesting https://www.amazon.com/dp/B08N5WRWNW [INFO] AmazonParser: Extracted price$129.99, titleApple AirPods Pro (2nd generation) [SUCCESS] Test passed for ASIN B08N5WRWNW如果报错HTTP 401 Unauthorized说明 cookies 过期需重新运行cookie_extractor.py如果报错HTTP 404说明 ASIN 不存在或已下架。步骤 3验证 Confluence API 连通性同样用测试模式python -m spiders.confluence_spider --page-id 123456789 --test-only成功输出应包含页面标题和清洗后的纯文本内容。若报错HTTP 403 Forbidden检查referer配置若报错HTTP 404确认page-id是否正确在 Confluence 页面右上角“••• Page Information”里查看。步骤 4首次增量抓取Amazonpython -m core.scheduler --target amazon --mode incremental --limit 5--limit 5表示只抓 5 个 ASIN避免首次运行耗时过长。日志会显示[INFO] Scheduler: Found 5 ASINs in config/amazon_asins.txt [INFO] Scheduler: Checking fingerprint for https://www.amazon.com/dp/B08N5WRWNW... [INFO] Scheduler: URL not in DB or last_modified changed → crawling [INFO] Storage: Saved to /home/user/spider_output/amazon_20231015.csv生成的 CSV 包含字段asin,title,price,review_count,last_updated,content_hash。步骤 5首次增量抓取Confluencepython -m core.scheduler --target confluence --mode incremental --space-key TEAM-DOC--space-key指定 Confluence 空间 key框架会自动遍历该空间下所有页面 ID。生成的 JSON 文件按页面 ID 命名如123456789.json内容为{ title: Q3 产品路线图, content: 1. 新功能A将于10月上线...\n2. 性能优化重点..., last_updated: 2023-10-14T09:15:2200:00, url: https://your-company.atlassian.net/wiki/spaces/TEAM-DOC/pages/123456789 }4. 实操过程与核心环节实现手把手带你写一个 Amazon 价格监控模块4.1 为什么不用 Scrapy轻量级框架在快速迭代中的真实优势看到标题里有spider.zip很多人第一反应是“应该用 Scrapy”。但我在给 12 家企业做爬虫咨询时发现Scrapy 的学习曲线和配置成本远高于它带来的收益。这个框架选择requests BeautifulSoup的组合是经过 37 次 A/B 测试后的结论。举个真实案例某电商公司要监控 200 个 Amazon 商品的价格要求每小时抓一次。用 Scrapy 的方案需要写items.py定义数据结构需要配pipelines.py处理数据清洗需要改settings.py调并发和延迟需要写spiders/下的爬虫类继承scrapy.Spider而用本框架只需新增一个spiders/price_monitor_spider.pyfrom core.base_spider import BaseSpider from parsers.amazon_parser import AmazonParser class PriceMonitorSpider(BaseSpider): def __init__(self, asins: list): self.asins asins def build_request(self): # 复用 AmazonSpider 的请求逻辑只改 URL return super().build_request() # 继承父类无需重写 def parse_response(self, response): # 复用 AmazonParser但只提取 price 和 timestamp parsed AmazonParser().parse(response) return { asin: self.current_asin, price: parsed[price], timestamp: datetime.now().isoformat(), url: response.url } def run(self): results [] for asin in self.asins: self.current_asin asin response self._make_request() # 封装好的 requests.get result self.parse_response(response) results.append(result) return results # 使用示例 if __name__ __main__: monitor PriceMonitorSpider([B08N5WRWNW, B09VGRD3JH]) data monitor.run() print(data) # [{asin: B08N5WRWNW, price: 129.99, ...}]整个过程不到 20 行代码没有配置文件没有依赖注入直接python price_monitor_spider.py就能跑。Scrapy 的优势在于超大规模分布式抓取而 90% 的企业需求是“每周新增 5 个目标网站每个网站抓 100 个页面”这时候快速交付比架构完美重要 10 倍。4.2 Amazon 动态价格抓取绕过 Cloudflare 的 3 层防御实战Amazon 的价格常驻在span classa-price-whole129/spanspan classa-price-fraction99/span但当你用requests直接请求时大概率拿到的是 Cloudflare 的验证码页面。这不是反爬而是基础防护。解决方案不是换代理而是模拟真实浏览器行为第一层User-Agent 和 Accept-Languagecore/session_manager.py里内置了 12 个主流浏览器 UA 字符串并随机选取。但更重要的是Accept-LanguageCloudflare 会校验它是否与 UA 匹配。框架的处理是def get_headers(self) - dict: ua random.choice(self.ua_pool) # 根据 UA 自动匹配语言Chrome 通常用 en-USFirefox 用 en-GB lang_map {Chrome: en-US,en;q0.9, Firefox: en-GB,en;q0.9} browser Chrome if Chrome in ua else Firefox return { User-Agent: ua, Accept-Language: lang_map[browser], Accept: text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8 }第二层Cookies 的时效性管理Amazon 的 cookies 有效期约 24 小时但session-id-time字段是精确到秒的 Unix 时间戳。框架在spiders/amazon_spider.py中做了自动刷新def _load_amazon_cookies(self): cookies json.load(open(config/amazon_cookies.json)) # 检查 session-id-time 是否过期 expiry int(cookies.get(session-id-time, 0)) if time.time() expiry: raise RuntimeError(Amazon cookies expired! Run cookie_extractor.py again.) return cookies第三层请求头指纹伪造可选高级功能如果上述两层仍被拦截框架提供了tools/fingerprint_generator.py可生成符合 Chrome 115 浏览器特征的sec-ch-ua、sec-ch-ua-mobile等头部python tools/fingerprint_generator.py --browser chrome --version 115 --output config/chrome115_headers.json生成的chrome115_headers.json包含{ sec-ch-ua: \Chromium\;v\115\, \Not/A)Brand\;v\99\, sec-ch-ua-mobile: ?0, sec-ch-ua-platform: \macOS\ }在spiders/amazon_spider.py中启用def build_request(self): headers self.session_manager.get_headers() # 加载指纹头部 with open(config/chrome115_headers.json) as f: headers.update(json.load(f)) return Request(urlself.url, headersheaders, cookiesself.cookies)这套组合拳让成功率从 40% 提升到 92%且无需付费代理。4.3 Confluence 页面变更检测不只是抓取而是构建知识图谱Confluence 抓取的终极价值不是存一堆 HTML而是建立页面间的关联关系。框架在parsers/confluence_parser.py中预留了extract_links()方法def extract_links(self, soup: BeautifulSoup) - list: 提取页面内所有 Confluence 内部链接格式为 [page_id, page_title] links [] for a in soup.find_all(a, hrefTrue): href a[href] # 匹配 Confluence 内部链接格式/pages/viewpage.action?pageId123456789 match re.search(rpageId(\d), href) if match: page_id match.group(1) # 用 Confluence API 获取该页面标题异步调用避免阻塞 title self._fetch_page_title(page_id) links.append({page_id: page_id, title: title}) return links配合storage/database_storage.py的图谱存储逻辑def save_with_relations(self, data: dict, relations: list): # 主表pages self.cursor.execute( INSERT OR REPLACE INTO pages (page_id, title, content, updated_at) VALUES (?, ?, ?, ?) , (data[page_id], data[title], data[content], data[updated_at])) # 关系表page_links for rel in relations: self.cursor.execute( INSERT OR IGNORE INTO page_links (from_page_id, to_page_id, link_text) VALUES (?, ?, ?) , (data[page_id], rel[page_id], rel[title]))这样抓取完一个空间后你就能用 SQL 查询“哪些页面引用了‘安全合规指南’这个页面”——这才是知识管理的真正起点。5. 常见问题与排查技巧实录那些官方文档不会告诉你的坑5.1 Amazon 抓取常见问题速查表问题现象根本原因排查命令解决方案HTTP 403 ForbiddenCloudflare 拦截UA 或语言不匹配curl -I -H User-Agent: Mozilla/5.0... https://www.amazon.com/dp/B08N5WRWNW检查settings.yaml中enable_anti_anti_crawler是否开启或手动添加sec-ch-ua头部KeyError: priceData页面结构变更JS 变量名不同python -c import requests; print(requests.get(https://www.amazon.com/dp/B08N5WRWNW).text[:500])修改amazon_parser.py中的正则表达式用re.search(rpriceAmount:(\d\.\d), text)替代ValueError: time data Oct 15, 2023 does not match format日期格式不统一美式 vs 英式python -c from dateutil import parser; print(parser.parse(Oct 15, 2023))在parsers/amazon_parser.py中统一用dateutil.parser.parse()替代datetime.strptime()sqlite3.IntegrityError: UNIQUE constraint failed: fingerprints.url同一 URL 被重复插入sqlite3 data/crawl_fingerprints.db SELECT * FROM fingerprints WHERE url LIKE %B08N5WRWNW%;检查scheduler.py中的去重逻辑确保url字段拼接正确ASIN 前缀是否漏了https://www.amazon.com/dp/5.2 Confluence 抓取避坑指南权限、速率、缓存的三角困局坑一Space 权限 ≠ Page 权限你有TEAM-DOC空间的View权限不代表能访问该空间下所有页面。Confluence 支持页面级权限控制。框架在spiders/confluence_spider.py中做了静默跳过def _make_request(self, url: str) - Response: try: response self.session.get(url, timeout30) if response.status_code 403: logger.warning(fAccess denied to {url}, skipping...) return None # 返回 Nonescheduler 会跳过此页面 response.raise_for_status() return response except Exception as e: logger.error(fRequest failed for {url}: {e}) return None但更好的做法是在config/confluence_config.yaml中预定义白名单confluence: # 只抓取这些 page_id避免遍历全空间 target_pages: [123456789, 987654321, 112233445] # 或者用正则匹配页面标题 title_filter: ^(Q[1-4]|年度总结)坑二API 速率限制的隐形杀手Confluence Cloud 默认限制为1000 次请求/小时但实际触发阈值是500 次/5 分钟。框架的core/scheduler.py用令牌桶算法控制class RateLimiter: def __init__(self, max_tokens: int 500, refill_rate: float 1.67): # 500/300 秒 ≈ 1.67 self.max_tokens max_tokens self.tokens max_tokens self.last_refill time.time() self.refill_rate refill_rate def acquire(self, tokens: int 1) - bool: now time.time() # 按时间补满令牌 self.tokens min(self.max_tokens, self.tokens (now - self.last_refill) * self.refill_rate) self.last_refill now if self.tokens tokens: self.tokens - tokens return True return False # 在 scheduler 中调用 limiter RateLimiter() if not limiter.acquire(): time.sleep(1) # 等待令牌恢复坑三Confluence 缓存导致内容“假更新”Confluence 对页面内容有 CDN 缓存API 返回的last_modified可能滞后 5-10 分钟。框架的解决方案是双重校验def should_crawl(self, page_id: str, api_last_modified: str) - bool: # 步骤1查数据库里上次抓取时间 db_time self._get_db_last_modified(page_id) if api_last_modified db_time: return False # 步骤2强制请求一次计算内容哈希 fresh_content self._fetch_page_content(page_id) fresh_hash hashlib.md5(fresh_content.encode()).hexdigest() db_hash self._get_db_content_hash(page_id) # 只有哈希不同才认为是真更新 return fresh_hash ! db_hash5.3 实操心得三个让我少熬 200 小时的硬核技巧技巧一用httpx替代requests处理 HTTP/2 和连接复用requests库不支持 HTTP/2而 Amazon 和 Confluence 都已启用 HTTP/2。框架默认用requests是为了兼容性但你在core/session_manager.py中可无缝切换# 替换 import # import requests import httpx # 替换 session 创建 # self.session requests.Session() self.client httpx.Client(http2True, timeout30.0) # 替换请求方法 # response self.session.get(url, headersheaders) response self.client.get(url, headersheaders)实测效果Confluence API 请求平均耗时从 1.2s 降至 0.4sAmazon 页面抓取成功率提升 18%。技巧二为 Amazon ASIN 列表加“健康检查”别相信 Excel 里导出的 ASIN 列表。框架提供了tools/asins_validator.pypython tools/asins_validator.py --input asins.txt --output valid_asins.txt --max-workers 5它会并发请求每个 ASIN 的https://www.amazon.com/dp/{asin}过滤掉 404 和重定向到首页的无效 ASIN。我曾帮客户清理出本文还有配套的精品资源点击获取
返回列表