Проанализируйте все ссылки на странице, посетите их, извлеките основную копию, затем продолжите эффективный обход - PullRequest
2 голосов
/ 06 ноября 2011

Так вот что у меня есть:

require 'rubygems'
require 'nokogiri'
require 'open-uri'

root_url = "http://boxerbiography.blogspot.com/2006/11/table-of-contents.html"
file_path = "boxer-noko.html"

site = Nokogiri::HTML(open(root_url))

titles = []
content = []

site.css(".entry a").each do |link|
    titles.push(link)

    content_url = link[:href]
    content_page = Nokogiri::HTML(open(content_url))

    content_page.css("#top p").each do |copy|
        content.push(copy)
    end

end

Но это делает n ^ n циклов. т. е. если на главной странице 5 ссылок, она переходит на первую, затем в content она присваивает ей значение всех 5 ссылок (с текущей вверху), затем она возвращается и уходит к следующему и продолжает делать это.

Таким образом, каждый фрагмент контента фактически возвращает контент для каждой отдельной ссылки, которая выглядит следующим образом:

Link 1

Copy associated with Link 1.
Copy associated with Link 2.
Copy associated with Link 3.
.
.
.

Link 2

Copy associated with Link 2.
Copy associated with Link 3.
Copy associated with Link 4.
Copy associated with Link 5.
Copy associated with Link 1.
.
.
.

etc.

Что я хотел бы сделать, так это вернуть:

Link 1

Copy associated with Link 1.

Link 2

Copy associated with Link 2.

Как можно более эффективным способом.

Как мне это сделать?

Edit1: Полагаю, простой способ думать об этом состоит в том, что в каждом массиве, скажем titles, я хотел бы хранить как ссылку, так и контент, связанный с этой ссылкой. Но не совсем уверен, как это сделать, учитывая, что мне нужно открыть два URI-соединения, чтобы проанализировать обе страницы и продолжать возвращаться к корню.

Итак, я представил это как:

title[0] = :href => "http://somelink.com", :content => "Copy associated with some link".

Но я не могу этого сделать, поэтому я вынужден сделать это, используя два массива, которые мне кажутся неоптимальными.

1 Ответ

2 голосов
/ 06 ноября 2011

Следующее создаст хеш с ключами URL, каждое значение URL является набором элементов абзаца Nokogiri.

require 'rubygems'
require 'nokogiri'
require 'open-uri'

root_url = "http://boxerbiography.blogspot.com/2006/11/table-of-contents.html"

site = Nokogiri::HTML(open(root_url))

contents = {}
site.css(".entry a").each do |link|
    content_url = link[:href]
    p "Fetching #{content_url}..."
    content_page = Nokogiri::HTML(open(content_url))
    contents[link[:href]] = content_page.css("#top p")
end

В качестве проверки работоспособности вы можете проверить содержимое одного из ключей, как этот:

contents[contents.keys.first]

Это может или не может быть тем, что вы на самом деле хотите, так как он сохранит все внутренние теги на месте (<br/> s, <i>...</i> s и т. Д.), Но это может бытьдовольно легко подправить, изменив содержимое.Или же это может быть просто обработано путем последующей обработки содержимого каждого URL.

Если вы хотите сохранить больше информации о каждом URL (например, текст ссылки), то вам, вероятно, нужно создать крошечный класс-оболочку с URL-адресом.и атрибуты заголовка.

В нынешнем виде код не выполняет никакой проверки, чтобы убедиться, что каждый URL-адрес извлекается только один раз - может быть, лучше создать Set URL-адресов для обеспечения уникальности, затемсоздайте карту, просматривая содержимое этого набора (URL).

...