2014-08-27 1 views
0

Я построил скрипт ruby ​​для скребка с использованием open-uri и nokogiri, я довольно новичок в этом, но все это работает на пару веб-сайтов, которые мне нужны для извлечения данных из которые имеют полный URL-адрес источника, кроме одного, который использует относительные URL-адреса.Ruby - Открытие абсолютного URL-адреса от относительного

Что делает скрипт, открывает страницу, создает массив открываемых страниц, затем просматривает и извлекает данные из css (а не xpath).

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

В моем случае, я думаю, Мне нужно добавить что-то в том месте, где он подталкивает URL-адреса, может ли кто-нибудь указать мне в правильном направлении? Это было бы очень оценено! Благодаря!

require 'open-uri' 
require 'nokogiri' 

PAGE_URL = "http://www.OMMITED.co.uk" 

page = Nokogiri::HTML(open(PAGE_URL, "User-Agent" => “OMMITED“)) 

links = page.css("a") 

links_array = Array.new 

links.each{|link| 
     url = link['href'].nil? ? 'empty' : link['href'] 
     if url.include? 'category' and !url.include? '/all' 
       links_array.push url 
     end 
} 
+0

Вы можете использовать регулярное выражение для проверки полного URL-адреса, что-то вроде/^ [\ w] *: \/\ // - если оно совпадает с префиксом корневой URL. Вспоминая тонкость «/» в начале относительного URL-адреса, означающего, что он начинается с корня пути после сервера, в отличие от относительных ссылок, начинающихся без косой черты, которые соответствуют каталогу текущей страницы. Я напишу ответ, но мне нужно больше знать доступные переменные. (Текущий полный URL и текущий путь к странице, в основном.) –

+0

Отредактировано для добавления переменных! – James

ответ

0

tl; dr: Короткий ответ внизу.

Хорошо, если у вас есть переменная класса называется @url, содержащий полное URL текущей страницы:

require 'uri' 

def full_url(rel, url) 
    return rel if rel.match /^[\w]*:\/\// 
    uri = URI(url) 
    if rel[0] == '/' 
    "#{uri.scheme}://#{uri.host}#{rel}" 
    else 
    path = uri.path.split('/')[0..-2].select{|m| !m.empty?}.join('/') 
    "#{uri.scheme}://#{uri.host}/#{path}/#{rel}" 
    end 
end 

Тогда вы можете позвонить:

links_array.push full_url(url, @url) 

Вы можете поместить метод в тот же класс или в вспомогательном классе. Он использует библиотеку Ruby URI для поиска соответствующих частей полностью квалифицированного URL-адреса, а затем создает новый из относительного пути.

Если относительный путь начинается с '/', он должен идти сразу после хоста.

Если он не начинается с символа '/', он должен находиться в том же виртуальном каталоге, что и текущая страница. Таким образом, если текущая страница:

http://www.host.com/aaa/bbb/ccc 

и относительный путь:

ddd 

, то выход должен быть:

http://www.host.com/aaa/bbb/ddd 

однако, если относительный путь:

/ddd 

тогда выход должен быть:

http://www.host.com/ddd 

Код:

uri.path.split('/')[0..-2].select{|m| !m.empty?}.join('/') 

принимает путь полного URL, разделяет его на '/' дает массив (['aaa','bbb', 'ccc']), затем удаляет последний элемент. (['aaa','bbb']). Выбор удаляет все пустые элементы, после чего соединение снова зашифровывает его.("aaa/bbb")

ИЛИ

вы могли бы сделать это скучный путь:

require 'uri' 

URI.join("http://www.host.com/aaa/bbb/ccc", "/ddd").to_s 
# => "http://www.host.com/ddd" 

URI.join("http://www.host.com/aaa/bbb/ccc", "ddd").to_s 
# => "http://www.host.com/aaa/bbb/ddd" 

данный код:

links.each{|link| 
    url = link['href'].nil? ? 'empty' : link['href'] 
    if url.include? 'category' and !url.include? '/all' 
      links_array.push url 
    end 
} 

Я бы переписать как:

links.each do |link| 
    url = link['href'].nil? ? 'empty' : link['href'] 
    if url.include? 'category' && !url.include? '/all' 
    full_url = URI.join(PAGE_URL, url).to_s 
    puts full_url 
    links_array << url 
    puts links_array.inspect 
    end 
end 

Примечание: S tylistically, многострочные блоки должны использовать do/end, а не {}. Отступы должны быть двумя пробелами. В скобках не должно быть пробелов. Оператор < < выступает за толкание. Всегда используйте & & в условных выражениях, а не and, который имеет гораздо более низкий приоритет и может вызывать проблемы. Смотрите руководство по стилю GitHub:

https://github.com/styleguide/ruby

puts будут там на основе ваших комментариев, мы надеемся, поможет вам понять, почему ваш массив не ведет. Как и должно быть, на основе кода, который вы там ввели. Однако я предпочел бы использовать отладчик. (Или byebug, если вы на Ruby 2.x)

+0

Спасибо за ваш ответ, я добавил ваш код и добавил переменную @url, которая привела к остановке ошибки такого файла или каталога, которая, как я думаю, указывает, что она объединяет два значения, но, похоже, не открывается массив URL, который мне нужно будет изучить, я попытаюсь исправить это и вернусь, чтобы подтвердить, что ваше разрешение работает! Благодаря! – James

+0

Проверьте отредактированный конец ответа, который показывает гораздо более простое и чистое решение. –

+0

Вдохновленный ваш последний комментарий, я пришел с этим 'code' @full_url = URI.join (PAGE_URL, URL) .to_s ставит @full_url links_array.push @full_url конец } ' код ' Он правильно соединяется (puts печатает полный URL-адрес), но не похоже, что он переходит к массиву. Можете ли вы увидеть какие-либо ошибки здесь, которые могли бы объяснить это? – James