簡體   English   中英

如何在Ruby中使用Nokogiri解析日期

[英]How to parse a date using Nokogiri in Ruby

我正在嘗試解析此頁面並拉起之后的日期

>p>From Date:

我得到錯誤

Invalid predicate: //b[text() = '<p>From Date: ' (Nokogiri::XML::XPath::SyntaxError)

來自“檢查元素”的xpath是

/html/body/div#timelineItems/table/tbody/tr/td/table.resultsTypes/tbody/tr/td/p

這是代碼示例:

#/usr/bin/ruby

require 'Nokogiri'
noko = Nokogiri::HTML('china.html')
noko.xpath("//b[text() = '<p>From Date: ").each do |b|
puts b.next_sibling.content.strip
end

這是文件://china.html


  
 
  
  
  
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

    <html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        
        <title>File </title>

    
      </head>
      <body>
        
            <div id ="timelineItems">
    <H2 id="telegram1"> Title </H2>
            <p><table cellspacing="0">
    <tr>
    <td width="2%">&nbsp;</td>
    <td width="75%">
    <table cellspacing="0" cellpadding="0" class="resultsTypes">
    <tr>
    <td width="5%" class="hide">&nbsp;</td>
    <td width="70%">
    <p>Template: <span class="bidi">ארכיון בן גוריון - מסמך</span></p>
    <p>Title: <a href="http://www.bing.com" title=""><span class="bidi">Meeting in China</span></a></p>

    <p>recipient: David Ben Gurion</p>
    <p>sender: Prime Minister of Union of Burma, Rangoon</p>
    <p>  Sub collection: <span class="bidi">התכתבות > תת-חטיבה מכתב</span></p>
    <p>From Date: 02/14/1936</p>
    <p>Link to file: <span class="bidi">תיק התכתבות  1956 ינואר</span></p>
    </td>
    </tr>
    <tr>
    <td colspan="2">
    </td>
    </tr>
    </table></td>
    <td class="actions">&nbsp;</td>
    </tr>
    </table>

    </p>
          </div>
          
    
    </body></html>

阿瑪丹的答案original.rb

 #/usr/bin/ruby require 'Nokogiri' noko = Nokogiri::HTML('china.html') date = noko.at_xpath("//p[starts-with(text(),'From Date: ')]").text() puts date formatted = date[/From Date: (.*)/, 1] puts formatted 
給出錯誤original.rb:5:in '<main>': undefined method 'text' for nil:NilClass (NoMethodError)

你不能用

noko = Nokogiri::HTML('china.html')

Nokogiri::HTMLNokogiri::HTML::Document.parse的快捷方式。 該文件說:

 .parse(string_or_io, url = nil, encoding = nil, options = XML::ParseOptions::DEFAULT_HTML) {|options| ... } ⇒ Object` 

... string_or_io可以是String,也可以是響應讀取和關閉的任何對象,例如IO或StringIO。 ...

'china.html'是一個字符串,但不是HTML。 看來您在想文件名就足夠了,但是Nokogiri並沒有打開任何東西,它只理解包含標記的字符串(HTML或XML)或響應read方法的IO類型對象。 比較這些:

require 'nokogiri'

doc = Nokogiri::HTML('china.html')
doc.to_html
# => "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body><p>china.html</p></body></html>\n"

與:

doc = Nokogiri::HTML('<html><body><p>foo</p></body></html>')
doc.to_html
# => "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body><p>foo</p></body></html>\n"

和:

doc = Nokogiri::HTML(open('http://www.example.org'))
doc.to_html[0..99]
# => "<!DOCTYPE html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta charset=\"utf-8\">\n    <met"

最后一個有效,因為OpenURI添加了讀取URL的功能來open ,從而響應read

open('http://www.example.org').respond_to?(:read) # => true

接下來的問題:

require 'nokogiri'
require 'open-uri'

html = <<EOT
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

    <title>File </title>


  </head>
  <body>

        <div id ="timelineItems">
<H2 id="telegram1"> Title </H2>
        <p><table cellspacing="0">
<tr>
<td width="2%">&nbsp;</td>
<td width="75%">
<table cellspacing="0" cellpadding="0" class="resultsTypes">
<tr>
<td width="5%" class="hide">&nbsp;</td>
<td width="70%">
<p>Template: <span class="bidi">ארכיון בן גוריון - מסמך</span></p>
<p>Title: <a href="http://www.bing.com" title=""><span class="bidi">Meeting in China</span></a></p>

<p>recipient: David Ben Gurion</p>
<p>sender: Prime Minister of Union of Burma, Rangoon</p>
<p>  Sub collection: <span class="bidi">התכתבות > תת-חטיבה מכתב</span></p>
<p>From Date: 02/14/1936</p>
<p>Link to file: <span class="bidi">תיק התכתבות  1956 ינואר</span></p>
</td>
</tr>
<tr>
<td colspan="2">
</td>
</tr>
</table></td>
<td class="actions">&nbsp;</td>
</tr>
</table>

</p>
      </div>


</body></html>
EOT

doc = Nokogiri::HTML(html)

解析完文檔后,可以使用輕松找到特定的<p>標記。

<table cellspacing="0" cellpadding="0" class="resultsTypes">

作為地標:

from_date = doc.at('table.resultsTypes p[6]').text
# => "From Date: 02/14/1936"

似乎更難獲得標題=“ Meeting in China”和link =“ bing.com”; 因為它們在同一條線上。

我正在使用CSS選擇器定義所需文本的路徑。 CSS比XPath更容易閱讀,盡管XPath更強大和更具描述性。 Nokogiri允許我們使用兩者之一,並允許我們使用searchat兩者一起使用。 at等效於search('some selector').first Nokogiri::XML::Node介紹了searchat CSS和XPath特定版本。

title_link = doc.at('table.resultsTypes p[2] a')['href'] # => "http://www.bing.com"
title = doc.at('table.resultsTypes p[2] span').text # => "Meeting in China"

您正在嘗試使用XPath:

/html/body/div#timelineItems/table/tbody/tr/td/table.resultsTypes/tbody/tr/td/p

但是,它對於正在使用的HTML無效。

注意選擇器中的tbody 看HTML,在<table>標記中的任何一個之后,都沒有<tbody>標記,因此XPath是錯誤的。 我懷疑這是由您的瀏覽器生成的,瀏覽器正在根據規范對HTML進行修正以添加<tbody> ,但是Nokogiri並未對HTML進行修正以添加<tbody>匹配,導致搜索失敗。 因此,不要依賴瀏覽器定義的選擇器,也不要相信瀏覽器對實際HTML源代碼的想法。


與其使用顯式選擇器,不如使用更好,更輕松,更智能的方法,在標記中查找特定的航路點,並使用這些航路點導航至所需的節點。 這是僅使用占位符以及XPath和CSS的混合來完成上述所有操作的示例:

doc.at('//p[starts-with(., "Title:")]').text  # => "Title: Meeting in China"
title_node = doc.at('//p[starts-with(., "Title:")]')
title_url = title_node.at('a')['href'] # => "http://www.bing.com"
title = title_node.at('span').text # => "Meeting in China"

因此,可以混合使用CSS和XPath。

from_date = noko.at_xpath('//p[starts-with(text(), "From Date:")]').text()
date = from_date[/From Date: (.*)/, 1]
# => "02/14/1936"

編輯:

說明:獲取文檔( // )中任何位置的第一個節點( #at_xpath ),以使[...] )文本內容( text() )以( starts-with(string, stringStart)"From Date" starts-with(string, stringStart)"From Date:" ),並獲取其文本內容( #text() ),並將其( = )存儲到變量from_datefrom_date )中。 然后,使用與文字字符"From Date: "匹配的正則表達式( /.../ ),從該文本( from_date )中提取第一組( #[regexp, 1] ),后跟任意數字( * )的任何字符( . )中的第一個捕獲組中將捕獲的( (...) ),將由#[regexp, 1]提取。

也,

Amadan的答案給出了一個錯誤

正如錫曼所解釋的,我沒有注意到您的Nokogiri結構已損壞。 noko = Nokogiri::HTML('china.html') (這不是我的答案的一部分)將為您提供一個單節點文檔,其中僅包含文本"china.html" ,而沒有<p>節點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM