如何递归抓取mavin.io所有末级分类对应的商品列表页链接
多级分类末级商品列表页抓取实现方案
实现逻辑
核心用深度优先递归遍历所有分类节点:
- 请求任意分类页后,优先提取页面上的所有子分类链接
- 存在子分类:依次递归请求每个子分类链接,继续下一级遍历
- 不存在子分类:判定为末级分类,将对应商品列表页链接存入结果集
完整实现代码
import requests import time from lxml.html import fromstring # 全局去重集合存储末级分类链接 end_category_links = set() # 请求头避免被反爬拦截 HEADERS = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36' } def crawl_category(url): # 增加延迟避免触发限流 time.sleep(0.5) try: resp = requests.get(url, headers=HEADERS, timeout=10) resp.raise_for_status() html = fromstring(resp.text) # 提取当前页面的子分类链接,选择器可根据页面实际结构调整 # 这里匹配所有指向分类页的a标签,可按实际DOM属性修改 sub_category_links = html.xpath('//div[contains(@class,"category-item")]//a/@href') # 子分类链接补全域名 sub_category_links = [f"https://mavin.io{i}" if i.startswith('/') else i for i in sub_category_links] if sub_category_links: # 存在子分类,继续递归遍历 for link in sub_category_links: crawl_category(link) else: # 无任何子分类,判定为末级,提取商品列表页链接 if '/search' in url: end_link = url else: cat_id = html.xpath('//meta[@name="category-id"]/@content') if not cat_id: return end_link = f"https://mavin.io/search?q=&cat={cat_id[0]}" end_category_links.add(end_link) except Exception as e: print(f"请求{url}出错:{str(e)}") if __name__ == '__main__': start_url = 'https://mavin.io/category' crawl_category(start_url) # 输出所有末级分类链接 print("共抓取到末级分类链接:") for link in end_category_links: print(link) # 支持导出到本地文件 with open('end_category_links.txt', 'w', encoding='utf-8') as f: f.write('\n'.join(end_category_links))
注意事项
- 代码中的XPath选择器需要根据页面实际DOM结构调整,可打开网站分类页按F12查看子分类节点的class、父容器属性,修改对应提取规则即可
- 如果请求频率高触发验证码或者403,可以增加代理IP、自动切换UA、加大延迟时间等逻辑适配
- 递归深度如果超过Python默认限制(默认1000层),可以手动调整递归深度阈值,或者把递归逻辑改成栈实现的非递归深度优先遍历
内容的提问来源于stack exchange,提问作者codewithawais
相关产品推荐
相关产品推荐

