2017-07-27 85 views
1

我試圖解析一些nmap XML通過Nokogiri檢索各種值,但有相當一段時間計算出遞歸。我想要的是抓住ip_address和具有status='open'子元素的任何port元素。我希望能夠把每一組成JSON對象保存到數據庫中列後顯示:Nokogiri檢索嵌套結果

到目前爲止,這是我的代碼:

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

如果您有關於清理代碼的任何建議,我所有的耳朵,以及!

回答

1

一切都與您的代碼似乎是工作很好,除了

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 
+0

啊,那是我的問題!所以從兒童'國家'元素的迴歸根本不是問題!謝謝 – Godzilla74

0

您是否知道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