使用 Nokogiri 检索嵌套结果
Retrieve nested results with Nokogiri
我正在尝试解析一些 nmap XML 以通过 Nokogiri 检索各种值,但花了很多时间来弄清楚递归。我想要的是获取 ip_address
和任何具有子元素 status='open'
的 port
元素。我希望能够将每个组放入一个 JSON 对象中以保存到数据库列中供以后显示:
到目前为止,这是我的代码:
require 'nokogiri'
require 'json'
doc = File.open("network_ports.xml") { |f| Nokogiri::XML(f) }
doc.xpath('//host').each do |host|
@ip_address = host.at_xpath("address[@addrtype='ipv4']").at_xpath("@addr").value
puts "Found Host: #{@ip_address}"
host.xpath('ports/port').each do |port|
if port.at_xpath("state[@state='open']")
puts port.at_xpath("port[@portid]").value
end
end
end
但是我的输出现在因以下错误而中断:
port_parser.rb:11:in `block (2 levels) in <main>': undefined method `value' for nil:NilClass (NoMethodError)
来自文件的一些相同输入:
<host starttime="1501187906" endtime="1501189103"><status state="up" reason="syn-ack" reason_ttl="0"/>
<address addr="10.10.10.1" addrtype="ipv4"/>
<hostnames>
<hostname name="eclipse" type="PTR"/>
</hostnames>
<ports><extraports state="closed" count="996">
<extrareasons reason="conn-refused" count="996"/>
</extraports>
<port protocol="tcp" portid="53"><state state="open" reason="syn-ack" reason_ttl="0"/><service name="domain" product="dnsmasq" version="2.45" method="probed" conf="10"><cpe>cpe:/a:thekelleys:dnsmasq:2.45</cpe></service></port>
<port protocol="tcp" portid="80"><state state="filtered" reason="syn-ack" reason_ttl="0"/><service name="http" product="DD-WRT milli_httpd" hostname="eclipse" method="probed" conf="10"/></port>
<port protocol="tcp" portid="443"><state state="open" reason="syn-ack" reason_ttl="0"/><service name="https" tunnel="ssl" method="table" conf="3"/></port>
<port protocol="tcp" portid="2222"><state state="open" reason="syn-ack" reason_ttl="0"/><service name="ssh" product="Dropbear sshd" version="0.52" extrainfo="protocol 2.0" ostype="Linux" method="probed" conf="10"><cpe>cpe:/a:matt_johnston:dropbear_ssh_server:0.52</cpe><cpe>cpe:/o:linux:linux_kernel</cpe></service></port>
</ports>
<times srtt="4727" rttvar="1840" to="100000"/>
</host>
我 运行 有问题吗,因为我依赖于 port
元素中的嵌套 state
元素,我需要它才能获得 portid
属性值出的?
最后,我只希望得到一些输出,例如:
Found host: 10.10.10.1
port 22/tcp open
port 23/tcp open
Found host: 10.10.10.2
port 443/tcp open
port 5432/tcp open
etc...
如果您对清理代码有任何建议,我也会洗耳恭听!
除了
之外,您的代码中的所有内容似乎都运行良好
puts port.at_xpath("port[@portid]").value
您已经在 port
元素处,所以您只需要 xpath @portid
puts port.at_xpath("@portid").value
并且,对于您的示例 network_ports.xml,输出
# Found Host: 10.10.10.1
# 53
# 443
# 2222
你知道NMAP gem吗?
require 'nmap/xml'
Nmap::XML.new('scan.xml') do |xml|
xml.each_host do |host|
puts "[#{host.ip}]"
host.each_port do |port|
puts " #{port.number}/#{port.protocol}\t#{port.state}\t#{port.service}"
end
end
end
我正在尝试解析一些 nmap XML 以通过 Nokogiri 检索各种值,但花了很多时间来弄清楚递归。我想要的是获取 ip_address
和任何具有子元素 status='open'
的 port
元素。我希望能够将每个组放入一个 JSON 对象中以保存到数据库列中供以后显示:
到目前为止,这是我的代码:
require 'nokogiri'
require 'json'
doc = File.open("network_ports.xml") { |f| Nokogiri::XML(f) }
doc.xpath('//host').each do |host|
@ip_address = host.at_xpath("address[@addrtype='ipv4']").at_xpath("@addr").value
puts "Found Host: #{@ip_address}"
host.xpath('ports/port').each do |port|
if port.at_xpath("state[@state='open']")
puts port.at_xpath("port[@portid]").value
end
end
end
但是我的输出现在因以下错误而中断:
port_parser.rb:11:in `block (2 levels) in <main>': undefined method `value' for nil:NilClass (NoMethodError)
来自文件的一些相同输入:
<host starttime="1501187906" endtime="1501189103"><status state="up" reason="syn-ack" reason_ttl="0"/>
<address addr="10.10.10.1" addrtype="ipv4"/>
<hostnames>
<hostname name="eclipse" type="PTR"/>
</hostnames>
<ports><extraports state="closed" count="996">
<extrareasons reason="conn-refused" count="996"/>
</extraports>
<port protocol="tcp" portid="53"><state state="open" reason="syn-ack" reason_ttl="0"/><service name="domain" product="dnsmasq" version="2.45" method="probed" conf="10"><cpe>cpe:/a:thekelleys:dnsmasq:2.45</cpe></service></port>
<port protocol="tcp" portid="80"><state state="filtered" reason="syn-ack" reason_ttl="0"/><service name="http" product="DD-WRT milli_httpd" hostname="eclipse" method="probed" conf="10"/></port>
<port protocol="tcp" portid="443"><state state="open" reason="syn-ack" reason_ttl="0"/><service name="https" tunnel="ssl" method="table" conf="3"/></port>
<port protocol="tcp" portid="2222"><state state="open" reason="syn-ack" reason_ttl="0"/><service name="ssh" product="Dropbear sshd" version="0.52" extrainfo="protocol 2.0" ostype="Linux" method="probed" conf="10"><cpe>cpe:/a:matt_johnston:dropbear_ssh_server:0.52</cpe><cpe>cpe:/o:linux:linux_kernel</cpe></service></port>
</ports>
<times srtt="4727" rttvar="1840" to="100000"/>
</host>
我 运行 有问题吗,因为我依赖于 port
元素中的嵌套 state
元素,我需要它才能获得 portid
属性值出的?
最后,我只希望得到一些输出,例如:
Found host: 10.10.10.1
port 22/tcp open
port 23/tcp open
Found host: 10.10.10.2
port 443/tcp open
port 5432/tcp open
etc...
如果您对清理代码有任何建议,我也会洗耳恭听!
除了
之外,您的代码中的所有内容似乎都运行良好puts port.at_xpath("port[@portid]").value
您已经在 port
元素处,所以您只需要 xpath @portid
puts port.at_xpath("@portid").value
并且,对于您的示例 network_ports.xml,输出
# Found Host: 10.10.10.1
# 53
# 443
# 2222
你知道NMAP gem吗?
require 'nmap/xml'
Nmap::XML.new('scan.xml') do |xml|
xml.each_host do |host|
puts "[#{host.ip}]"
host.each_port do |port|
puts " #{port.number}/#{port.protocol}\t#{port.state}\t#{port.service}"
end
end
end