RSS1.0を検索する際の名前空間の指定
ここ最近Pythonのlxmlモジュールを試していて、RSS1.0形式のデータをXPathで検索する場合は名前空間を指定しなければならないことを知った。
例えば、RSSから各記事のタイトル部分を取得したいとして
RSS2.0の場合、「 /rss/channel/item/title 」でOKなのだが、
RSS1.0の場合、「 /rdf:RDF/item/title 」というようにルートノードから順に並べただけでは取得できない。
RSS1.0、RSS2.0、それぞれをダウンロードする。
$ wget -q http://www.pheedo.jp/f/gigazine_1 && mv gigazine_1 gigazine_rss1.xml $ wget -q http://www.pheedo.jp/f/gigazine_2 && mv gigazine_2 gigazine_rss2.xml $ ls -tl | grep gigazine -rw-rw-r-- 1 hogeuser hogeuser 38043 9月 28 20:58 gigazine_rss1.xml -rw-rw-r-- 1 hogeuser hogeuser 49547 9月 28 20:58 gigazine_rss2.xml
以下、検証用スクリプト
#!/usr/bin/env python # -*- coding:utf8 -*- from lxml import etree def find_by_xpath(src, xpath, ns={}): print 'SOURCE = %s' % src print 'XPATH = %s' % xpath print 'NAMESPACE = %s' % ns finded = [] try: finded = etree.parse(src).xpath(xpath, namespaces=ns) print '> finded = %sitems\n' % len(finded) except etree.Error, err: print '> error = %s "%s"\n' % (err.__class__, err) #return finded # rss2.0 # XPath式をルートノードから順に書く => OK: 取得できる find_by_xpath('gigazine_rss2.xml', '/rss/channel/item/title') # rss1.0 # XPath式をルートノードから順に書く => NG: エラーが発生する find_by_xpath('gigazine_rss1.xml', '/rdf:RDF/item/title') # rss1.0 # XPath式の指定に加えて、rss1.0データのルートノード部分の # 名前空間定義に従って、名前空間rdfを指定する => NG: 取得できない(0件) find_by_xpath('gigazine_rss1.xml', '/rdf:RDF/item/title', {'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'}) # rss1.0 # XPath式の指定、名前空間rdfの指定に加えて、別名のない名前空間に # 自分で適当な別名(以下の例では"hoge")を指定する => OK: 取得できる find_by_xpath('gigazine_rss1.xml', '/rdf:RDF/hoge:item/hoge:title', {'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'hoge': 'http://purl.org/rss/1.0/'})
以下、実行結果
$ python test_lxml_xpath2.py SOURCE = gigazine_rss2.xml XPATH = /rss/channel/item/title NAMESPACE = {} > finded = 36items SOURCE = gigazine_rss1.xml XPATH = /rdf:RDF/item/title NAMESPACE = {} > error = lxml.etree.XPathEvalError "Undefined namespace prefix" SOURCE = gigazine_rss1.xml XPATH = /rdf:RDF/item/title NAMESPACE = {'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'} > finded = 0items SOURCE = gigazine_rss1.xml XPATH = /rdf:RDF/hoge:item/hoge:title NAMESPACE = {'hoge': 'http://purl.org/rss/1.0/', 'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'} > finded = 37items
以下の記事がすごく参考になった。
オフィスで見る夜明け:C#でRSS - livedoor Blog(ブログ)