2012-02-04 2 views
1

웹 페이지의 여러 부분에서 텍스트를 가져 와서 배열 (웹 페이지 당 하나의 색인)에 푸시하려고합니다. 다음 코드는 영원히 반복됩니다. 이유는 알 수 없습니다.Nokogiri 라이브러리를 사용한 Neverending Loop; 왜

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

+2

나는 당신이 반환 값에 대해 혼란스러워한다고 생각합니다. 첫 번째 방법은 결과를 반환해야합니다. 맞습니까? 그것이 작성된 방법은 URL을 반환합니다. – pguardiario

+0

언급 한 바와 같이 반환 값에는 문제가 있지만 왜 반복되어야하는지는 알 수 없습니다. 디버깅을 시도 했습니까? – tokland

+0

테스트를 위해 사용하고있는 몇 개의 URL을 게시하십시오. –

답변

2

패턴 빈 배열 + 각 + (즉, 마지막 코드에서 실종됐다) + 반환 배열를 밀어 - 문헌 초록 (루비 here와 함수형 프로그래밍에 더)>map

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 
2

@pguardiario가 맞습니다. Ruby 메서드에서 블록의 마지막 줄 또는 반환 값은 암시 적으로 반환됩니다. 따라서 귀하의 경우에는 results 대신에 urls.each의 반환 값을 반환했습니다.

그러나 말했다되는 것으로, 여기에 Enumerable module를 사용하여 작성하는 더 관용적 방법입니다.

다음 코드 단편에 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 
+0

조심해, 당신은 주사와지도를 에뮬레이트하고 있습니다! – tokland

+0

및 array.reduce (: +) -> array.join – tokland

+0

+1에서 메서드 밖으로 XPath 문을 당깁니다. –

관련 문제