Ruby, Python - XML(XPath) 解析速度検証(Nokogiri, lxml)!
Updated:
Ruby の XML パーサ Nokogiri で XML 解析した場合と、 Python の XML パーサ lxml で XML 解析した場合の実行速度の差を検証してみました。
0. 前提条件
- Ruby 2.5.0, Python 3.6.4 での作業を想定。
- Ruby 用 XML パーサ Nokogiri がインストール済みであること。
- Python 用 XML パーサ lxml がインストール済みであること。
- 以下で紹介する検証結果は、使用する XML の構造等により若干異なることもあるかもしれない、ということに留意。
1. 検証に使用する XML ファイル
以下のような XML を使用する。(実際の「気象庁防災情報 XML」通知用 Atom フィードを流用)
File: test.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ja">
<title>JMAXML publishing feed</title>
<subtitle>this feed is published by JMA</subtitle>
<updated>2018-01-01T01:33:01+09:00</updated>
<id>urn:uuid:f57b5866-0c8c-3c92-9aff-10a715cdf48b</id>
<link href="http://www.jma.go.jp/" rel="related"/>
<link href="http://xml.kishou.go.jp/feed/extra.xml" rel="self"/>
<link href="http://alert-hub.appspot.com/" rel="hub"/>
<rights>Published by Japan Meteorological Agency</rights>
<entry>
<title>気象特別警報・警報・注意報</title>
<id>urn:uuid:34847d17-e9e0-356a-9b84-c1041d55c088</id>
<updated>2017-12-31T16:32:15Z</updated>
<author><name>名古屋地方気象台</name></author>
<link href="http://xml.kishou.go.jp/data/34847d17-e9e0-356a-9b84-c1041d55c088.xml" type="application/xml"/>
<content type="text">【愛知県気象警報・注意報】愛知県では、1日夜遅くまで強風や高波に、1日朝まで濃霧による視程障害に注意してください。</content>
</entry>
<entry>
<title>気象警報・注意報(H27)</title>
<id>urn:uuid:994ab034-7c1b-356e-a507-1544a54ff374</id>
<updated>2017-12-31T16:32:15Z</updated>
<author><name>名古屋地方気象台</name></author>
<link href="http://xml.kishou.go.jp/data/994ab034-7c1b-356e-a507-1544a54ff374.xml" type="application/xml"/>
<content type="text">【愛知県気象警報・注意報】愛知県では、1日夜遅くまで強風や高波に、1日朝まで濃霧による視程障害に注意してください。</content>
</entry>
<entry>
<title>気象警報・注意報</title>
<id>urn:uuid:c7c222a8-9e4d-3a81-8fda-b018c12756c7</id>
<updated>2017-12-31T16:32:15Z</updated>
<author><name>名古屋地方気象台</name></author>
<link href="http://xml.kishou.go.jp/data/c7c222a8-9e4d-3a81-8fda-b018c12756c7.xml" type="application/xml"/>
<content type="text">【愛知県気象警報・注意報】愛知県では、1日夜遅くまで強風や高波に、1日朝まで濃霧による視程障害に注意してください。</content>
</entry>
</feed>
2. 検証用 Ruby スクリプトの作成
各 entry
タグ内の title
の値を取得する。(10,000回ループ)
File: xml_parse_test.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#! /usr/local/bin/ruby
#
# Ruby script to verify the speed of xml(xpath) parsing by Nokogiri.
#
require 'nokogiri'
class XmlParse
def initialize(loop_cnt)
@doc = Nokogiri::XML(File.read("test.xml"))
@ns = {"a" => "http://www.w3.org/2005/Atom"}
@cnt = loop_cnt
end
def parse_test
@cnt.times do |i|
@doc.xpath("//a:entry", @ns).each do |e|
title = e.xpath("a:title", @ns).first.text
end
end
rescue => e
raise
end
end
exit 0 unless __FILE__ == $0
begin
CNT = 10000
o = XmlParse.new(CNT)
t_0 = Time.now
o.parse_test
puts "LOOP(#{CNT}): #{Time.now - t_0} secs."
rescue => e
$stderr.puts "[#{self.class.name}.#{__method__}] #{e}"
e.backtrace.each{ |tr| $stderr.puts "\t#{tr}" }
exit 1
end
3. 検証用 Python スクリプトの作成
前述 Ruby スクリプト同様、各 entry
タグ内の title
の値を取得する。(10,000回ループ)
File: xml_parse_test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#! /usr/local/bin/python3.6
"""
Python script to verify the speed of xml(xpath) parsing by lxml.
"""
import sys
import time
import traceback
from lxml import etree
class XmlParse:
def __init__(self, loop_cnt):
self.doc = etree.parse("test.xml")
self.ns = {"a": "http://www.w3.org/2005/Atom"}
self.cnt = loop_cnt
def parse_test(self):
try:
for i in range(self.cnt):
for e in self.doc.xpath("//a:entry", namespaces=self.ns):
title = e.xpath("a:title", namespaces=self.ns)[0].text
except Exception as e:
raise
if __name__ != '__main__':
sys.exit()
try:
CNT = 10000
o = XmlParse(CNT)
t_0 = time.time()
secs = o.parse_test()
print("LOOP({}): {} secs.".format(CNT, time.time() - t_0))
except Exception as e:
traceback.print_exc()
sys.exit(1)
4. 検証スクリプトの実行
$ ./xml_parse_test.rb
LOOP(10000): 1.515421197 secs.
$ ./xml_parse_test.py
LOOP(10000): 1.0317723751068115 secs.
(何回か実行し、平均的なものを掲載)
5. 結果
Python の方が Ruby の 1.5倍近く 速かった。(想定どおり)
当方がこれまで Ruby で作成してきた Web スクレイピングツールを Python に移植しようか検討中。
以上。
Comments