我想从谷歌搜索查询中删除链接。
我无法将结果保存在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=(.*)&sa=U/)[0][0]
end
parse_results(doc)
puts links
答案 0 :(得分:2)
问题在于可变范围,并且很常见。
我会像这样重写代码:
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=(.*)&sa=U/)[0][0]
end
links = parse_results(doc)
puts links
links
可以定义为实例,类或全局变量,但所有这些都有代码味道。您将试图规避范围界定,这对于避免在变量堆栈上浪费空间来说真的是您的朋友。
scan
将返回一系列结果,因此请将结果推送到_links
。
map
对你正在做的事情不是正确的方法; each
更合适,因为您在HTML中搜索class="g"
的结果。使用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/&sa=U&ei=z33SU5a-LMPaoASe94GYBw&ved=0CBQQFjAA&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/&sa=U&ei=gYDSU-D3AsHXiwLj1oGwBg&ved=0CBQQFjAA&usg=AFQjCNG59EuN3nByaD1NEg7t3garmotJTg\"><b>Estimation immobiliere</b> gratuite - MeilleursAgents.com</a>",
# "<a href=\"/url?q=http://www.drimki.fr/estimation-immobiliere-gratuite&sa=U&ei=gYDSU-D3AsHXiwLj1oGwBg&ved=0CBoQFjAB&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&sa=U&ei=gYDSU-D3AsHXiwLj1oGwBg&ved=0CCAQFjAC&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/&sa=U&ei=gYDSU-D3AsHXiwLj1oGwBg&ved=0CCYQFjAD&usg=AFQjCNEjsDh8wYnj9XQBuuotGWOtJKrBYQ\">LaCoteImmo - <b>Estimation immobili\u00E8re</b> et Prix immobilier</a>",
# "<a href=\"/url?q=http://www.efficity.com/estimation-immobiliere/&sa=U&ei=gYDSU-D3AsHXiwLj1oGwBg&ved=0CCwQFjAE&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/&sa=U&ei=gYDSU-D3AsHXiwLj1oGwBg&ved=0CDIQFjAF&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&sa=U&ei=gYDSU-D3AsHXiwLj1oGwBg&ved=0CDgQFjAG&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/&sa=U&ei=gYDSU-D3AsHXiwLj1oGwBg&ved=0CD4QFjAH&usg=AFQjCNFelUOIWlvj09l5RIG0KF8CiY9kLw\"><b>Estimation immobiliere</b> gratuite avec MeilleursAgents.com</a>",
# "<a href=\"/url?q=http://www.refleximmo.com/estimation-immobiliere-gratuite-appartement&sa=U&ei=gYDSU-D3AsHXiwLj1oGwBg&ved=0CEQQFjAI&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&sa=U&ei=gYDSU-D3AsHXiwLj1oGwBg&ved=0CEoQFjAJ&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",
...
这应该为您提供足够的信息来更有力地重写您的代码。 Regular expressions are not good tools for parsing HTML,最好尽可能使用经过充分测试的预制车轮,例如URI。
我说这种方法更健壮的原因是因为这段代码:
links << tempo.scan(/<a href=\"\/url\?q=(.*)&sa=U/)[0][0]
这种搜索非常容易破解。网址格式可以快速更改,尤其是当网站怀疑人们正在抓取他们的网页并且他们不想要抓紧时,例如Google。他们可以轻松地更改参数的顺序,它们可以改变链接在页面中的写入方式等,因为HTML允许非常自由地格式化源,浏览器仍然会向用户呈现相同的视图。想象一下,如果Google选择呈现如下链接,那么您将获得乐趣:
<a
href="/url?amp;sa=U&q=...
正则表达式会破坏,导致代码中断,而使用URI和Nokogiri向下钻取将继续有效。
答案 1 :(得分:0)
如果你制作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=(.*)&sa=U/)[0][0]
end
parse_results(doc)
puts @links