簡體   English   中英

為什么我的代碼中會出現“未定義的局部變量或方法”?

[英]Why do I get “undefined local variable or method” in my code?

我想從Google搜索查詢中刪除鏈接。

我無法在TAB(鏈接)中保存結果:

error : test.rb:17:in `parse_result': undefined local variable or
method `links' for main:Object (NameError)

這是我的代碼:

require 'open-uri'
require 'nokogiri'

doc = Nokogiri::HTML(open('https://www.google.fr/search?q=estimation+immobilier'))

links = []

def parse_results(doc)
    doc.search('.g').map do |element|
      parse_block(element)
    end
end


def parse_block(element)
    tempo = element.search('.r').to_s
    links << tempo.scan(/<a href=\"\/url\?q=(.*)&amp;sa=U/)[0][0]
end

parse_results(doc)

puts links

問題是可變范圍,並且非常常見。

我會像這樣重寫代碼:

require 'open-uri'
require 'nokogiri'

doc = Nokogiri::HTML(open('https://www.google.fr/search?q=estimation+immobilier'))

def parse_results(doc)
  _links = []
  doc.search('.g').each do |element|
    _links << parse_block(element)
  end
  _links
end

def parse_block(element)
  tempo = element.search('.r').to_s
  tempo.scan(/<a href=\"\/url\?q=(.*)&amp;sa=U/)[0][0]
end

links = parse_results(doc)

puts links

links可以定義為實例,類或全局變量,但所有這些都有代碼味道。 你將試圖規避范圍界定,這對於避免在變量堆棧上浪費空間來說真的是你的朋友。

scan將返回一個結果數組,因此將其結果推送到_links

map不是你正在做的事情的正確方法; 因為你循環遍歷在HTML中搜索class="g"的結果,所以each都更合適。 使用map ,您可以編寫parse_results()如:

def parse_results(doc)
  doc.search('.g').map { |element| parse_block(element) }
end

parse_block()編寫不正確,或者至少可以為Nokogiri寫出更多的東西。 如果您在使用XML或HTML解析器時不得不求助於使用正則表達式,那么您應該知道應該重新考慮的事情。 看看發生了什么,這是代碼在通過parse_results()parse_block()潛水時看到的內容:

doc.search('.g').first.search('.r').to_s
# => "<h3 class=\"r\"><a href=\"/url?q=http://www.meilleursagents.com/estimation-immobiliere/&amp;sa=U&amp;ei=z33SU5a-LMPaoASe94GYBw&amp;ved=0CBQQFjAA&amp;usg=AFQjCNH_Nfe9VGSqO8AU_mc3TL_ZsyNRFw\"><b>Estimation immobiliere</b> gratuite - MeilleursAgents.com</a></h3>\n"

您正嘗試從鏈接中獲取參數,因此請使用Nokogiri干凈地執行此操作,而不是嘗試使用模式和scan 我打開頁面並像你一樣解析它,然后嘗試了這個:

doc.search('.g h3.r a').map(&:to_html)
# => ["<a href=\"/url?q=http://www.meilleursagents.com/estimation-immobiliere/&amp;sa=U&amp;ei=gYDSU-D3AsHXiwLj1oGwBg&amp;ved=0CBQQFjAA&amp;usg=AFQjCNG59EuN3nByaD1NEg7t3garmotJTg\"><b>Estimation immobiliere</b> gratuite - MeilleursAgents.com</a>",
#     "<a href=\"/url?q=http://www.drimki.fr/estimation-immobiliere-gratuite&amp;sa=U&amp;ei=gYDSU-D3AsHXiwLj1oGwBg&amp;ved=0CBoQFjAB&amp;usg=AFQjCNH4HpJ9WRzLhpSGVfRwcogxuJPZDA\"><b>Estimation immobili\u00E8re</b> gratuite (maison, appartement <b>...</b> - Drimki</a>",
#     "<a href=\"/url?q=http://www.pap.fr/evaluation/estimation-immobiliere&amp;sa=U&amp;ei=gYDSU-D3AsHXiwLj1oGwBg&amp;ved=0CCAQFjAC&amp;usg=AFQjCNGcAeTDeib6hBVcD931CGyDRoPx6A\"><b>Estimation immobili\u00E8re</b> avec Particulier \u00E0 Particulier | De <b>...</b> - P.a.p</a>",
#     "<a href=\"/url?q=http://www.lacoteimmo.com/&amp;sa=U&amp;ei=gYDSU-D3AsHXiwLj1oGwBg&amp;ved=0CCYQFjAD&amp;usg=AFQjCNEjsDh8wYnj9XQBuuotGWOtJKrBYQ\">LaCoteImmo - <b>Estimation immobili\u00E8re</b> et Prix immobilier</a>",
#     "<a href=\"/url?q=http://www.efficity.com/estimation-immobiliere/&amp;sa=U&amp;ei=gYDSU-D3AsHXiwLj1oGwBg&amp;ved=0CCwQFjAE&amp;usg=AFQjCNH_2RgWZ4VMeP29eKt1MAZTySOSZA\"><b>Estimation immobili\u00E8re</b> - Efficity</a>",
#     "<a href=\"/url?q=http://www.paruvendu.fr/pa/prix-immobilier-prix-m2-estimation-gratuite-bien-immobilier/&amp;sa=U&amp;ei=gYDSU-D3AsHXiwLj1oGwBg&amp;ved=0CDIQFjAF&amp;usg=AFQjCNFz0VTEKcTJrzIgT4nwOMnm85vX5g\"><b>Estimation</b> gratuite d'un bien <b>immobilier</b> - ParuVendu</a>",
#     "<a href=\"/url?q=http://www.meilleurtaux.com/services-immo/vendre-un-bien-immobilier/estimation-immobiliere.html&amp;sa=U&amp;ei=gYDSU-D3AsHXiwLj1oGwBg&amp;ved=0CDgQFjAG&amp;usg=AFQjCNGjSqsVQe0GB0uzTvewfR-FtfGUww\"><b>Estimer</b> la valeur de son bien <b>immobilier</b>- Meilleurtaux.com</a>",
#     "<a href=\"/url?q=http://prix-immobilier.latribune.fr/estimation-immobiliere/&amp;sa=U&amp;ei=gYDSU-D3AsHXiwLj1oGwBg&amp;ved=0CD4QFjAH&amp;usg=AFQjCNFelUOIWlvj09l5RIG0KF8CiY9kLw\"><b>Estimation immobiliere</b> gratuite avec MeilleursAgents.com</a>",
#     "<a href=\"/url?q=http://www.refleximmo.com/estimation-immobiliere-gratuite-appartement&amp;sa=U&amp;ei=gYDSU-D3AsHXiwLj1oGwBg&amp;ved=0CEQQFjAI&amp;usg=AFQjCNErmk1sUrmrAPU188KyyfYG_O0cMw\"><b>Estimation</b> gratuite de votre appartement en ligne - Refleximmo</a>",
#     "<a href=\"/url?q=http://www.capital.fr/immobilier/estimation-immobiliere&amp;sa=U&amp;ei=gYDSU-D3AsHXiwLj1oGwBg&amp;ved=0CEoQFjAJ&amp;usg=AFQjCNEVRbp_kOwOmT86TWHEvFbjm6W3nA\"><b>Estimation Immobili\u00E8re</b> - Immobilier - Capital.fr</a>"]

更全面的CSS顯着縮小了返回的結果。

一點調整導致:

doc.search('.g h3.r a').map{ |a| a['href'] }
# => ["/url?q=http://www.meilleursagents.com/estimation-immobiliere/&sa=U&ei=OoHSU7KaEszwoAS__YDoCA&ved=0CBQQFjAA&usg=AFQjCNFNCH0iR3pr0fQX6wSjcj1_s3CsRg",
#     "/url?q=http://www.drimki.fr/estimation-immobiliere-gratuite&sa=U&ei=OoHSU7KaEszwoAS__YDoCA&ved=0CBoQFjAB&usg=AFQjCNGUbFcsWWQY-bc8Vu-d-GD9YFcbVg",
#     "/url?q=http://www.pap.fr/evaluation/estimation-immobiliere&sa=U&ei=OoHSU7KaEszwoAS__YDoCA&ved=0CCAQFjAC&usg=AFQjCNGztbZlDWWGS4kNPHzR06ayRdAQKg",
#     "/url?q=http://www.lacoteimmo.com/&sa=U&ei=OoHSU7KaEszwoAS__YDoCA&ved=0CCYQFjAD&usg=AFQjCNEZK_JVduJKJvFpDDXu4yIsTXGMFg",
#     "/url?q=http://www.efficity.com/estimation-immobiliere/&sa=U&ei=OoHSU7KaEszwoAS__YDoCA&ved=0CCwQFjAE&usg=AFQjCNHHc-GuJoHXTx3N3_Ex_fz1KUp1cg",
#     "/url?q=http://www.paruvendu.fr/pa/prix-immobilier-prix-m2-estimation-gratuite-bien-immobilier/&sa=U&ei=OoHSU7KaEszwoAS__YDoCA&ved=0CDIQFjAF&usg=AFQjCNGmwWmo19asoooWz6Lbh0YMOC8wlg",
#     "/url?q=http://www.meilleurtaux.com/services-immo/vendre-un-bien-immobilier/estimation-immobiliere.html&sa=U&ei=OoHSU7KaEszwoAS__YDoCA&ved=0CDgQFjAG&usg=AFQjCNFJ_fAsPBmZvVU60jRLh-yKzvuEiw",
#     "/url?q=http://prix-immobilier.latribune.fr/estimation-immobiliere/&sa=U&ei=OoHSU7KaEszwoAS__YDoCA&ved=0CD4QFjAH&usg=AFQjCNHHaVmKGg4jiaT-6AwZAfby2-H4sg",
#     "/url?q=http://www.refleximmo.com/estimation-immobiliere-gratuite-appartement&sa=U&ei=OoHSU7KaEszwoAS__YDoCA&ved=0CEQQFjAI&usg=AFQjCNGiBMMYrK-EO9wqIh82eW2uFT0n8w",
#     "/url?q=http://www.capital.fr/immobilier/estimation-immobiliere&sa=U&ei=OoHSU7KaEszwoAS__YDoCA&ved=0CEoQFjAJ&usg=AFQjCNEf8FQuKCYBMXBB5FA2dJ2gor4Wmg"]

在這一點上,很明顯我們正在查看絕對URL數組,可以使用Ruby的內置URI類來處理:

require 'uri'
doc.search('.g h3.r a').map{ |a| 
  uri = URI.parse(a['href'])
  query_hash = Hash[URI::decode_www_form(uri.query)]
  query_hash['q']
}
# => [
    "http://www.meilleursagents.com/estimation-immobiliere/",
    "http://www.drimki.fr/estimation-immobiliere-gratuite",
    "http://www.pap.fr/evaluation/estimation-immobiliere",
    ...

這應該給你足夠的信息來更有力地重寫代碼。 正則表達式不是解析HTML的好工具,最好盡可能使用經過良好測試的預先構建的輪子,比如URI

我說這種方法更健壯的原因是因為這段代碼:

links << tempo.scan(/<a href=\"\/url\?q=(.*)&amp;sa=U/)[0][0]

這種搜索很容易破裂。 網址格式可以快速更改,尤其是當網站懷疑人們正在抓取他們的網頁並且他們不想要抓緊時,例如Google。 他們可以輕松地更改參數的順序,它們可以改變鏈接在頁面中的寫入方式等,因為HTML允許非常自由地格式化源,瀏覽器仍然會向用戶呈現相同的視圖。 想象一下,如果谷歌選擇呈現如下鏈接,您將擁有的樂趣:

<a
 href="/url?amp;sa=U&q=...

正則表達式會破壞,導致代碼中斷,而使用URI和Nokogiri向下鑽取將繼續工作。

如果你創建links和實例變量,它可以工作:

require 'open-uri'
require 'nokogiri'

doc = Nokogiri::HTML(open('https://www.google.fr/search?q=estimation+immobilier'))

@links = []

def parse_results(doc)
    doc.search('.g').map do |element|
      parse_block(element)
    end
end


def parse_block(element)
    tempo = element.search('.r').to_s
    @links << tempo.scan(/<a href=\"\/url\?q=(.*)&amp;sa=U/)[0][0]
end

parse_results(doc)

puts @links

暫無
暫無

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

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