智能爬取:用 Trafilatura 发现和抓取整站内容

自动解析 Sitemap 和 RSS Feed 发现全站页面,URL 去重与过滤,配合代理实现整站内容采集。

亿牛云技术团队2026年4月23日2 分钟阅读

从 Sitemap 发现 URL

Trafilatura 可以自动解析网站的 Sitemap 文件(XML 和 TXT 格式):

import trafilatura

# 自动发现并解析 sitemap
urls = trafilatura.sitemaps.sitemap_search("https://example.com")
print(f"发现 {len(urls)} 个 URL")

# 查看前 10 个
for url in urls[:10]:
    print(url)

sitemap_search() 会自动尝试常见路径(/sitemap.xml/sitemap_index.xml)并解析嵌套的 sitemap 索引文件。

指定 sitemap URL

from trafilatura.sitemaps import parse_sitemap

# 直接指定 sitemap URL
urls = parse_sitemap("https://example.com/sitemap.xml")
print(f"从 sitemap 提取了 {len(urls)} 个 URL")

URL 过滤

发现大量 URL 后,通常需要筛选目标:

# 只保留 /blog/ 路径下的文章
blog_urls = [u for u in urls if "/blog/" in u]

# 排除特定路径
filtered = [u for u in urls if not "/tag/" in u and not "/author/" in u]

# 限定域名
same_domain = [u for u in urls if u.startswith("https://example.com")]
过滤方式代码适用场景
路径前缀url.startswith("https://example.com/blog/")只采集博客
路径包含"/article/" in url只采集文章页
排除模式"/tag/" not in url排除标签页
正则匹配re.search(r"/\d{4}/\d{2}/", url)匹配日期路径

从 RSS/ATOM Feed 获取更新

适合持续追踪更新的站点:

from trafilatura.feeds import find_feed_urls, parse_feed

# 自动发现 feed
feed_urls = find_feed_urls("https://example.com")
print(f"发现 {len(feed_urls)} 个 feed")

# 解析 feed 中的文章
for feed_url in feed_urls:
    entries = parse_feed(feed_url)
    for entry in entries:
        print(f"{entry.title}: {entry.url}")

支持格式:RSS 2.0、ATOM、JSON Feed。

增量更新策略

import json
from trafilatura.feeds import find_feed_urls, parse_feed

# 加载已处理的 URL
try:
    with open("processed_urls.json", "r") as f:
        processed = set(json.load(f))
except FileNotFoundError:
    processed = set()

# 获取最新 feed
feed_urls = find_feed_urls("https://example.com/blog")
new_articles = []

for feed_url in feed_urls:
    entries = parse_feed(feed_url)
    for entry in entries:
        if entry.url not in processed:
            new_articles.append(entry.url)

print(f"新增 {len(new_articles)} 篇文章")

# 保存已处理列表
processed.update(new_articles)
with open("processed_urls.json", "w") as f:
    json.dump(list(processed), f)

组合使用:自动发现并提取

import trafilatura
from trafilatura.sitemaps import sitemap_search
from trafilatura.feeds import find_feed_urls, parse_feed

# 1. 从 sitemap 发现历史文章
sitemap_urls = sitemap_search("https://example.com")
blog_urls = [u for u in sitemap_urls if "/blog/" in u]

# 2. 从 feed 发现最新文章
feed_urls = find_feed_urls("https://example.com/blog")
feed_article_urls = []
for feed_url in feed_urls:
    entries = parse_feed(feed_url)
    feed_article_urls.extend([e.url for e in entries])

# 3. 合并去重
all_urls = list(set(blog_urls + feed_article_urls))
print(f"共发现 {len(all_urls)} 篇独立文章")

# 4. 批量提取正文
for url in all_urls[:5]:  # 先试前 5 篇
    downloaded = trafilatura.fetch_url(url)
    result = trafilatura.extract(downloaded, output_format="markdown")
    if result:
        print(f"✅ {url}")

配合代理进行整站采集

使用 16YUN API 代理时,可以先提取 IP 列表,再分配给批量请求:

import trafilatura
import requests
import random

# 用 API 代理提取一批 IP
api_url = "http://ip.16yun.cn:817/myip/pl/xxx/?s=xxx&u=user&format=json&count=20"
response = requests.get(api_url)
proxy_list = response.json()  # 返回 [{ip:port}, ...]

# 批量提取正文——每次随机选一个代理
for url in all_urls:
    proxy = random.choice(proxy_list)
    proxies = {
        "http": f"http://user:pass@{proxy['ip']}:{proxy['port']}",
        "https": f"http://user:pass@{proxy['ip']}:{proxy['port']}",
    }

    try:
        resp = requests.get(url, proxies=proxies, timeout=15)
        resp.encoding = "utf-8"
        result = trafilatura.extract(resp.text, output_format="markdown")
        if result:
            # 保存结果
            with open(f"articles/{url.split('/')[-1]}.md", "w") as f:
                f.write(result)
            print(f"✅ {url}")
    except Exception as e:
        print(f"❌ {url}: {e}")

错误处理要点

参照 16YUN 帮助文档中的错误码处理:

状态码原因应对
429请求频率过高降低并发、增加间隔、更换 IP
407代理认证失败核对用户名密码
504目标站超时重试 2-3 次,跳过持续失败页面

CLI 方式

# 通过 sitemap 发现 URL
trafilatura --sitemap https://example.com/sitemap.xml

# 通过 feed 发现 URL
trafilatura --feed https://example.com/feed.xml

# 从 URL 列表文件批量提取
trafilatura --list urls.txt --output-dir ./articles

注意事项

  • Sitemap 可能包含大量 URL(数万甚至百万级),建议先过滤再提取
  • 注意 robots.txt 的爬取限制,控制请求频率
  • 长期运行的采集任务建议加入断点续传机制,记录已处理的 URL
  • 配合 16YUN 爬虫代理的隧道模式可以简化代理管理——设置一个入口即可

需要企业代理方案?

我们可根据目标站点、并发规模与稳定性目标提供定制方案。