如何可靠发现非标准位置的站点地图?Python爬虫优化需求
SEO站点地图发现爬虫优化方案
一、扩展站点地图发现技巧
除了robots.txt和通用路径,这些实用方法能覆盖更多场景:
- 解析首页HTML的
<link rel="sitemap">标签:很多站点会在首页<head>中添加该标签指向站点地图 - 尝试压缩格式:优先探测
.xml.gz、.txt.gz后缀的路径,不少站点会用压缩版减少带宽消耗 - HEAD转GET降级:遇到HEAD请求返回405/404时,改用带
Range: bytes=0-0的GET请求(仅获取响应头,避免下载大文件) - 跟踪重定向:开启请求的自动重定向,捕获3xx响应后的最终URL,部分站点地图会藏在重定向后的位置
- 挖掘CMS专属路径:不同CMS有默认的站点地图位置(见下文优先级列表)
- 分析robots.txt的Disallow规则:尝试在允许爬取的目录下追加
sitemap.xml等后缀,部分站点会把地图放在内容目录下
二、Python代码改进实现
核心改进点
- 异步并发探测:用
aiohttp提升探测效率,配合信号量控制并发数 - HEAD→GET降级逻辑:解决部分服务器对HEAD响应不可靠的问题
- 扩充优先级路径列表:整合通用+CMS专属路径
- 自动去重与重定向跟踪:避免重复处理同一资源
- 压缩站点地图解析支持:处理
.gz格式的地图文件
完整代码片段
import asyncio import aiohttp import gzip import xml.etree.ElementTree as ET from urllib.parse import urljoin, urlparse from robots import RobotFileParser # 候选路径列表(按优先级从高到低排序) CANDIDATE_PATHS = [ # 通用高频路径 "/sitemap.xml", "/sitemap.txt", "/sitemap.xml.gz", "/sitemap_index.xml", "/sitemap-index.xml", # WordPress专属(WP5.5+默认路径优先) "/wp-sitemap.xml", "/wp-sitemap-index.xml", "/wp-content/sitemap.xml", "/sitemap-posttype-post.xml", # Shopify专属 "/sitemap_products.xml", "/sitemap_collections.xml", # Joomla专属 "/component/sitemap/", "/index.php?option=com_sitemap", # Drupal专属 "/sitemap", "/sitemap.xml.gz", ] async def fetch_sitemap_urls(base_url, session, semaphore): sitemap_urls = set() parsed_base = urlparse(base_url) base_domain = f"{parsed_base.scheme}://{parsed_base.netloc}" # 1. 解析robots.txt提取站点地图 robots_url = urljoin(base_domain, "/robots.txt") rp = RobotFileParser() rp.set_url(robots_url) try: rp.read() for sitemap in rp.site_maps(): sitemap_urls.add(sitemap) except Exception as e: print(f"[WARN] 解析robots.txt失败: {e}") # 2. 并发探测所有候选路径 async def probe_single_path(path): target_url = urljoin(base_domain, path) async with semaphore: # 先尝试HEAD请求(轻量探测) try: async with session.head(target_url, allow_redirects=True, timeout=10) as resp: if resp.status in (200, 301, 302): sitemap_urls.add(str(resp.url)) return except (aiohttp.ClientError, asyncio.TimeoutError): pass # HEAD失败,降级为带Range的GET请求(仅获取响应头) try: headers = {"Range": "bytes=0-0"} async with session.get(target_url, allow_redirects=True, timeout=10, headers=headers) as resp: if resp.status in (200, 301, 302): sitemap_urls.add(str(resp.url)) except (aiohttp.ClientError, asyncio.TimeoutError): print(f"[WARN] 探测路径失败: {target_url}") tasks = [probe_single_path(path) for path in CANDIDATE_PATHS] await asyncio.gather(*tasks) return list(sitemap_urls) async def parse_sitemap_content(sitemap_url, session): """解析站点地图内容(支持压缩格式)""" parsed_url = urlparse(sitemap_url) content = None try: async with session.get(sitemap_url, timeout=15) as resp: if resp.status != 200: print(f"[ERROR] 无法获取站点地图: {sitemap_url}") return [] content = await resp.read() # 处理压缩格式 if parsed_url.path.endswith(".gz"): try: content = gzip.decompress(content) except gzip.BadGzipFile: print(f"[WARN] 不是有效的GZIP文件: {sitemap_url}") return [] # 解析XML格式的站点地图 root = ET.fromstring(content) ns = {"sm": "http://www.sitemaps.org/schemas/sitemap/0.9"} urls = [elem.text for elem in root.findall(".//sm:loc", ns)] return urls except Exception as e: print(f"[ERROR] 解析站点地图失败: {sitemap_url}, 错误: {e}") return [] async def main(): target_url = "https://example.com" # 速率控制:每个域名同时最多2个请求,避免给服务器造成压力 semaphore = asyncio.Semaphore(2) async with aiohttp.ClientSession() as session: # 发现所有站点地图URL sitemap_urls = await fetch_sitemap_urls(target_url, session, semaphore) print(f"\n发现的站点地图URL:") for url in sitemap_urls: print(f"- {url}") # 解析每个站点地图的内容 print(f"\n解析站点地图内容:") for url in sitemap_urls: page_urls = await parse_sitemap_content(url, session) for page in page_urls[:5]: # 仅展示前5条示例 print(f" - {page}") if __name__ == "__main__": asyncio.run(main())
依赖安装
pip install aiohttp python-robots
三、开源工具与库推荐
- python-robots:专业的robots.txt解析库,比手动解析更可靠,支持站点地图提取
- sitemap-parser:专门解析各种格式站点地图的库,自动处理压缩和索引型地图
- Scrapy + scrapy-sitemap:适合大规模爬取场景,scrapy-sitemap插件可自动发现并解析站点地图
- WordPress专属:可直接调用WP REST API(
/wp-json/wp/v2/sitemaps)获取官方站点地图,或使用上述代码中的专属路径
四、合规爬取与速率控制建议
- 严格遵守robots.txt:即使站点地图未在robots.txt中列出,也不得爬取被Disallow的目录下的内容
- 速率与并发控制:
- 单域名请求间隔至少1秒,并发数不超过5(根据服务器响应调整)
- 用异步信号量(如代码中的
Semaphore)限制并发数
- 伦理规范:
- 避免在业务高峰时段(工作日9-18点)爬取商业站点
- 不爬取需要身份验证的站点地图,除非获得站点所有者明确授权
- 保留爬取日志(请求时间、URL、响应状态),以备合规检查
- 错误处理:设置合理的超时时间(10-15秒),捕获并处理网络错误,避免无限重试
内容的提问来源于stack exchange,提问作者Mujahid Mughal
相关产品推荐
相关产品推荐

