2015-05-08 37 views
1

在我的文本文件中是一個URL列表。使用機械化我使用該列表解析出標題和元描述。然而,其中一些URL頁面沒有meta描述其停止我的劇本有一個零誤差:如何忽略來自Mechanize的已分析值的循環中的零值?

undefined method `[]' for nil:NilClass (NoMethodError) 

我讀過起來,如果我使用Rails看到的解決方案,但對Ruby我已經只看到rejectcompact作爲忽略零值的可能解決方案。我在循環結尾添加了compact,但這似乎沒有做任何事情。

require 'rubygems' 
require 'mechanize' 

File.readlines('parsethis.txt').each do |line| 
    page = Mechanize.new.get(line) 
    title = page.title 
    metadesc = page.at("head meta[name='description']")[:content] 
    puts "%s, %s, %s" % [line.chomp, title, metadesc] 
end.compact! 

這只是在這樣的文本的URL列表:

http://www.a.com 
http://www.b.com 

這是什麼將在控制檯輸出示例:

http://www.a.com, Title, This is a description. 

如果內的URL列表沒有關於該特定頁面的描述或標題,它拋出了零錯誤。我不希望它跳過任何網址,我希望它能通過整個列表。

+0

一種方式是'page.at(「head meta [name ='description']」)。attributes [:content]'。 –

+0

當頁面沒有描述內容時,你想要發生什麼?完全跳過該條目或返回沒有兩個結尾逗號的字符串?你爲什麼'放'生成的字符串?你想要屏幕輸出,然後依靠'puts'的副作用返回輸出的值嗎?一般來說,這不是我們如何編寫這些代碼,所以對數據的更好描述會對您有所幫助。另外,如果您給出了一些示例URL和輸出示例,它會非常有幫助。這看起來像一個XY問題,你問了Y但是需要詢問X. –

+0

@theTinMan不是那麼複雜。我不希望任何條目被跳過,只是當它在控制檯上輸出時(通過puts)它不會因爲沒有描述而拋出錯誤。只要您擁有網址,機械化寶石可以讓您從網頁獲取數據。所以我有一個文本文件,它有逐行列表的url。控制檯將輸出url,除了其相關的html標題和meta描述,如下所示:http:// www.a.com,Title,這是控制檯中每行的描述。 –

回答

0

這裏是一個辦法做到這一點:

Edit(對於添加的需求不跳過任何網址):

metadesc = page.at("head meta[name='description']") 
puts "%s, %s, %s" % [line.chomp, title, metadesc ? metadesc[:content] : "N/A"] 
+0

謝謝,但它似乎立即拋出零錯誤,而不是通過列表產生錯誤之前,一旦有沒有描述或標題的網址。 –

+0

@mr。灰箱測試儀 - 請參閱編輯。 – seph

+0

使nil值成爲條件工作的三元運算符。我很快就會調整,以確定它的標題。謝謝你的幫助! –

0

這是未經測試,但我會做這樣的事情:

require 'open-uri' 
require 'nokogiri' 

page_info = {} 
File.foreach('parsethis.txt') { |url| 
    page = Nokogiri::HTML(open(url)) 
    title = page.title 
    meta_desc = page.at("head meta[name='description']") 
    meta_desc_content = meta_desc ? meta_desc[:content] : nil 
    page_info[url] = {:title => title, :meta_desc => meta_desc_content} 
} 

page_info.each do |url, info| 
    puts [ 
    url, 
    info[:title], 
    info[:meta_desc] 
    ].join(', ') 
end 
  • File.foreach迭代讀取文件,單獨返回每一行。
  • page.title如果頁面沒有標題,則返回nil;標題可選頁面。
  • 我打破了訪問meta-description分爲兩個步驟。 Meta標籤在HTML中是可選的,因此它們可能不存在,此時將返回零。試圖訪問content=參數會導致異常。我想這就是你所看到的。

    取而代之的是,在我的代碼中,meta_desc_content在找到元描述標籤時有條件地賦值,或者nil。

該代碼使用URL及其關聯標題和元描述的鍵/值對填充page_info散列。我這樣做是因爲散列散列或散列數組是一種非常方便的結構,適用於各種輔助操作,如將信息作爲JSON返回或插入到數據庫中。

作爲第二步,代碼迭代該散列,檢索每個鍵/值對。然後它將這些值加入到一個字符串中並打印出來。

有很多事情在你的代碼,或者是錯誤的,或者不是我會做他們:

  • File.readlines('parsethis.txt').each返回一個數組,你就必須遍歷。這不是可擴展的,也不是有效的。File.foreachFile.readlines(...).each快,所以要養成使用它的習慣,除非你確定你知道爲什麼你應該使用readlines
  • 對於Nokogiri和OpenURI可以做得更快的事情,您可以使用機械化。機械化是一個偉大的工具如果您正在使用表單並需要導航一個網站,但您沒有這樣做,所以相反,您正在拖動額外的代碼重量,這是不必要的。不要那樣做;這導致了其他方面的慢節目。
  • page.at("head meta[name='description']")[:content]是等待中的例外。正如我上面所說,meta-descriptions不一定會在頁面中存在。如果沒有,那麼你試圖做nil[:content]這肯定會引發異常。相反,按照你想要的數據工作,你可以在你試圖獲取它的內容之前確保元描述存在。
  • 你不能像你那樣使用compactcompact!each塊不會返回數組,這是您需要的類compactcompact!。你可以使用map,但邏輯本來就很亂,而map內部的puts很少使用。 (可能不應該使用更有可能,但這是一個不同的主題。)
+0

那麼...... OpenURI無法處理負載,並在運行時超時。儘管感謝您的意見和解釋。 –

+0

超時很少出現OpenURI的問題。服務器更可能拒絕發送文件並關閉連接。如果你反覆點擊服務器並超出連接限制,這可能發生,如果你不是一個好的網絡公民,這很容易發生。 –