如何用Python Scrapy解析XML站点地图?解析无结果求助
问题:Scrapy爬取XML站点地图时选择器无效、XMLFeedSpider无输出
尝试爬取XML站点地图:https://comercialtrevino.com/sitemap/sitemaprssatom_products.xml,先通过Scrapy Shell调试再编写爬虫提取目标URL,但遇到以下问题:
- Scrapy Shell选择器全部返回空数组
执行过的命令:
scrapy shell "https://comercialtrevino.com/sitemap/sitemaprssatom_products.xml" scrapy shell -s ROBOTSTXT_OBEY=False "https://comercialtrevino.com/sitemap/sitemaprssatom_products.xml"
尝试的选择器:
response.css("body") response.css("entry") response.css("url") response.css("span.html-tag") response.css("title") response.xpath("//entry") response.xpath("//loc") response.xpath("//url") response.xpath("//span") response.xpath("//title")
所有输出都是空数组,但浏览器打开能看到大量<entry>标签,开发者工具有span.html-tag,view(response)也能看到<loc>标签。
- XMLFeedSpider无日志/打印输出
编写的爬虫代码:
from scrapy.spiders import XMLFeedSpider from scrapy.item import Item class Trevi_Spider(XMLFeedSpider): name = 'trevi' start_urls = ["https://comercialtrevino.com/sitemap/sitemaprssatom_products.xml",] iterator = 'iternodes' namespaces = ['g', "http://base.google.com/ns/1.0"] #itertag = "g:link" itertag = 'entry' def parse_node(self, response, node): self.log('oiiiiiiiiiiiiiiiiiiiiiii ----------------> ', node, self.itertag) self.logger.info(f"Hi this is a {self.itertag} node!: {''.join(node.getall())}") item = Item() #item["src"] = node.xpath("/text()").get() item["src"] = node.xpath("//g:link/text()").get() print('oiiiiiiiiiiiiiiiiiiiii ------------------>', item) return item
控制台看不到任何打印或日志。
解决方案
一、Scrapy Shell选择器无效的修复
该XML站点地图带有XML命名空间,直接用标签名选择会失效,必须指定命名空间前缀:
- 先在Shell中查看XML的根命名空间:
response.xpath('namespace-uri(/*)').get()
会得到Atom标准命名空间:http://www.w3.org/2005/Atom。
- 正确的选择器写法:
- XPath方式:先注册命名空间,再带前缀选择
# 注册Atom命名空间 response.selector.register_namespace('atom', 'http://www.w3.org/2005/Atom') # 选择所有entry标签 response.xpath('//atom:entry') # 提取entry下的loc标签文本(商品URL) response.xpath('//atom:entry/atom:loc/text()').getall() - CSS方式:用
|分隔命名空间前缀和标签名response.css('atom|entry') response.css('atom|entry atom|loc::text').getall()
注意:浏览器看到的
span.html-tag是XML的渲染元素,不是原始响应内容,Scrapy抓取的是原始XML,所以无法通过选择器定位到它。
二、XMLFeedSpider无输出的修复
爬虫的核心问题是命名空间配置错误和itertag未指定命名空间前缀,修正后的代码如下:
from scrapy.spiders import XMLFeedSpider from scrapy.item import Item, Field class Trevi_Spider(XMLFeedSpider): name = 'trevi' start_urls = ["https://comercialtrevino.com/sitemap/sitemaprssatom_products.xml"] iterator = 'iternodes' # 命名空间需配置为字典:键是前缀,值是命名空间URI namespaces = { 'atom': 'http://www.w3.org/2005/Atom', 'g': 'http://base.google.com/ns/1.0' } # itertag必须带命名空间前缀,否则无法匹配节点 itertag = 'atom:entry' def parse_node(self, response, node): self.log(f'找到entry节点: {node.xpath("atom:loc/text()").get()}') self.logger.info(f"当前entry的URL: {node.xpath('atom:loc/text()').get()}") item = Item() item.fields['src'] = Field() # 用相对路径选择当前entry下的g:link,避免全局重复搜索 item["src"] = node.xpath('g:link/text()').get() print(f'提取的商品链接: {item["src"]}') return item
关键修复点:
namespaces必须是字典格式,而非列表;itertag需添加atom:前缀,指定命名空间下的entry节点;- 提取子节点时用相对路径(去掉
//),避免全局搜索导致的重复或错误; - 给Item添加
Field定义,确保数据能正常存储。
三、额外注意事项
- 先确认请求成功:在Shell中执行
response.status,确保返回200; - 若遇反爬,可添加自定义User-Agent:
scrapy shell -s 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" "https://comercialtrevino.com/sitemap/sitemaprssatom_products.xml"
内容的提问来源于stack exchange,提问作者Tezcatlipoca0000
相关产品推荐
相关产品推荐

