我试图从网页的各个部分提取文本,并将它们推送到一个数组中(每个网页一个索引)。以下代码永远循环,我不知道为什么:
def pull_text(urls)
results = []
urls.each do |something|
doc = Nokogiri::HTML(open(something))
main_text = doc.xpath('//div[@class="modText"]').inner_text
blue_text = doc.xpath('//div[@class="Text color2"]').inner_text
grey_text = doc.xpath('//div[@class="Text color1"]').inner_text
table_text = doc.xpath('//div[@class="Table color"]').inner_text
all_text = main_text + blue_text + grey_text + table_text
results << all_text
end
end
我还注意到,当我不将doc.xpath行分配给变量时,它将永远不循环地运行,但我不知道如何将所有这些都推到数组中。
然而,我确实注意到,当我向该方法提供单个url时,它是有效的。然而,我需要该方法能够处理多个url,而不仅仅是一个。
def grab_text(url)
doc = Nokogiri::HTML(open(url))
main_text = doc.xpath('//div[@class="modText"]').inner_text
blue_text = doc.xpath('//div[@class="Text color2"]').inner_text
grey_text = doc.xpath('//div[@class="Text color1"]').inner_text
table_text = doc.xpath('//div[@class="Table color"]').inner_text
all_text = main_text + blue_text + grey_text + table_text
end
很抱歉设计得不太好。我已经生疏了,对编程还是有点陌生S
模式空数组+每个+推送+返回数组(代码中缺少最后一个)->map
(更多关于Ruby函数编程的信息)
def pull_text(urls)
urls.map do |url|
doc = Nokogiri::HTML(open(url))
main_text = doc.xpath('//div[@class="modText"]').inner_text
blue_text = doc.xpath('//div[@class="Text color2"]').inner_text
grey_text = doc.xpath('//div[@class="Text color1"]').inner_text
table_text = doc.xpath('//div[@class="Table color"]').inner_text
main_text + blue_text + grey_text + table_text
end
end
抽象常见模式:
def pull_text(urls)
urls.map do |url|
doc = Nokogiri::HTML(open(url))
["modText", "Text color2", "Text color1", "Table color"].map do |klass|
doc.xpath("//div[@class='#{klass}']").inner_text
end.join
end
end
@pguardianio,是正确的。在Ruby方法中,块的最后一行或返回值是隐式返回的。因此,在您的情况下,您返回的是urls.each
的返回值,而不是results
。
尽管如此,这里有一种使用Enumerable模块编写它的更惯用的方法。
我在下面的代码片段中使用了Enumerable的以下方法-inject,map。
TEXT_XPATHS = [ '//div[@class="modText"]',
'//div[@class="Text color2"]',
'//div[@class="Text color1"]',
'//div[@class="Table color"]' ]
#
# extract_text_from( a_single_url )
#
# extract_text_from( ["a", "list", "of", "urls"] )
#
def extract_text_from(urls)
Array(urls).inject([]) do |results, url|
html = Nokogiri::HTML( open(url) )
texts = TEXT_XPATHS.map { |xpath| html.xpath(xpath).inner_text }
results << texts.join
end
end