【问题标题】:how to parse a sitemap.xml file using scrapy's XmlFeedSpider?如何使用 scrapy 的 XmlFeedSpider 解析 sitemap.xml 文件?
【发布时间】:2011-04-08 17:52:34
【问题描述】:

我正在尝试使用 scrapy 解析 sitemap.xml 文件,站点地图文件类似于下面的文件,但具有更多 url 节点。

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:video="http://www.sitemaps.org/schemas/sitemap-video/1.1">
    <url>
        <loc>
            http://www.site.com/page.html
        </loc>
        <video:video>
            <video:thumbnail_loc>
                http://www.site.com/thumb.jpg
            </video:thumbnail_loc>
            <video:content_loc>http://www.example.com/video123.flv</video:content_loc>
            <video:player_loc allow_embed="yes" autoplay="ap=1">
                http://www.example.com/videoplayer.swf?video=123
            </video:player_loc>
            <video:title>here is the page title</video:title>
            <video:description>and an awesome description</video:description>
            <video:duration>302</video:duration>
            <video:publication_date>2011-02-24T02:03:43+02:00</video:publication_date>
            <video:tag>w00t</video:tag>
            <video:tag>awesome</video:tag>
            <video:tag>omgwtfbbq</video:tag>
            <video:tag>kthxby</video:tag>
        </video:video>
    </url>
</urlset>

我查看了相关的scrapy's documentation,我写了下面的sn-p来看看我的做法是否正确(似乎我没有^^):

class SitemapSpider(XMLFeedSpider):
    name = "sitemap"
    namespaces = [
        ('', 'http://www.sitemaps.org/schemas/sitemap/0.9'),
        ('video', 'http://www.sitemaps.org/schemas/sitemap-video/1.1'),
    ]
    start_urls = ["http://example.com/sitemap.xml"]
    itertag = 'url'

    def parse_node(self, response, node):
        print "Parsing: %s" % str(node)

但是当我运行蜘蛛时,我得到了这个错误:

File "/.../python2.7/site-packages/scrapy/utils/iterators.py", line 32, in xmliter
    yield XmlXPathSelector(text=nodetext).select('//' + nodename)[0]
    exceptions.IndexError: list index out of range

我认为我没有正确定义“默认”命名空间 (http://www.sitemaps.org/schemas/sitemap/0.9),但我找不到如何执行此操作。

迭代url 节点然后能够从其子节点中提取所需信息的正确方法是什么?


回答:

不幸的是,我无法使用 XMLFeedSpider(这应该是使用 scrapy 解析 XML 的方式),但由于 simplebias 的回答,我已经能够找到一种方法来实现这种“老派方式”。我想出了以下代码(这一次有效!):

class SitemapSpider(BaseSpider):
    name = 'sitemap'
    namespaces = {
        'sitemap': 'http://www.sitemaps.org/schemas/sitemap/0.9',
        'video': 'http://www.sitemaps.org/schemas/sitemap-video/1.1',
    }

    def parse(self, response):
        xxs = XmlXPathSelector(response)
        for namespace, schema in self.namespaces.iteritems():
            xxs.register_namespace(namespace, schema)
        for urlnode in xxs.select('//sitemap:url'):
            extract_datas_here()

【问题讨论】:

    标签: python xml namespaces sitemap scrapy


    【解决方案1】:

    Scrapy 在后台使用 lxml / libxml2,最终调用 node.xpath() 方法来执行选择。 xpath 表达式中任何带有命名空间的元素都必须加上前缀,并且必须传递一个映射来告诉选择器每个前缀解析到哪个命名空间。

    下面是一个例子来说明在使用node.xpath()方法时如何将前缀映射到命名空间:

    doc = '<root xmlns="chaos"><bar /></root>'
    tree = lxml.etree.fromstring(doc)
    tree.xpath('//bar')
    []
    tree.xpath('//x:bar', namespaces={'x': 'chaos'})
    [<Element {chaos}bar at 7fa40f9c50a8>]
    

    没有使用过这个scrapy XMLFeedSpider 类,我猜你的命名空间映射和itertag 需要遵循相同的方案:

    class SitemapSpider(XMLFeedSpider):
        namespaces = [
            ('sm', 'http://www.sitemaps.org/schemas/sitemap/0.9'),
            ]
         itertag = 'sm:url'
    

    【讨论】:

    • 非常感谢,我无法使用 XMLFeedSpider 做到这一点,但您极大地帮助我找到了另一种方法。
    • 很高兴我能帮上忙!
    【解决方案2】:

    我发现 hxs 和 xxs 之间的区别很有帮助。我发现很难找到 xxs 对象。我正在尝试使用这个

    x = XmlXPathSelector(response)
    

    当这些对我需要的东西来说效果更好时。

    hxs.select('//p/text()').extract()
    

    xxs.select('//title/text()').extract()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-02
      相关资源
      最近更新 更多