Как проанализировать файл sitemap.xml, используя scml XmlFeedSpider?

1

Я пытаюсь разобрать sitemap.xml файлы с помощью scrapy, файлы sitemap выглядят следующим образом с гораздо большим количеством узлов 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>

Я просмотрел связанную документацию по скрипированию, и я написал следующий фрагмент, чтобы узнать, правильно ли я делаю (и, похоже, я не ^^):

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 (который должен быть способом анализа XML с помощью scrapy), но, благодаря ответу 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()
Теги:
namespaces
scrapy
sitemap

2 ответа

4
Лучший ответ

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>]

Без использования этого класса Scope XMLFeedSpider я предполагаю, что ваша карта пространства имен и itertag должны следовать одной и той же схеме:

class SitemapSpider(XMLFeedSpider):
    namespaces = [
        ('sm', 'http://www.sitemaps.org/schemas/sitemap/0.9'),
        ]
     itertag = 'sm:url'
  • 0
    Большое спасибо, я не смог сделать это с помощью XMLFeedSpider, но вы очень помогли мне найти другой способ сделать это.
  • 0
    Круто, рад, что могу помочь!
1

Я обнаружил, что разница между hxs и xxs полезна. Мне было трудно найти объект xxs. Я пытался использовать этот

x = XmlXPathSelector(response)

Когда они работали намного лучше для того, что мне было нужно.

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

или

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню