2010-04-27 1 views
3

Я хочу обработать все ссылки, кроме внешних со всего веб-сайта. Есть ли простой способ определить, что ссылка является внешней и пропустить ее?обрабатывать все ссылки, кроме внешних (ruby + mechanize)

Мой код выглядит так далеко, как (сайт URL передается через параметр командной строки)

Я использую Mechanize (0.9.3) и рубин 1.8.6 (2008-08-11 номера патчей 287) [i386-mswin32]

Пожалуйста, обратите внимание, что веб-сайт может использовать относительный путь, так что нет хоста/домена, и это делает его немного более сложным

require 'mechanize' 

def process_page(page) 
    puts 
    puts page.title 
    STDIN.gets 
    page.links.each do |link| 
process_page($agent.get(link.href)) 
    end 
end 

$agent = WWW::Mechanize.new 
$agent.user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.1.4) Gecko/20091016 Firefox/3.5.4' 
process_page($agent.get(ARGV[0])) 

ответ

7

У URI есть некоторые методы, которые позволяют легко увидеть, просматриваете ли вы локальный URL-адрес или один на другом сайте.

Это небольшая модификация из .route_to URI() документы, например:

 
require 'uri' 

URI.parse('/main.rbx?page=1').host # => nil 
URI.parse('main.rbx?page=1').host # => nil 

Внутренних URL-адрес не имеет хозяина, так что я бы разбор URL-адрес в вопросе и посмотреть, чтобы увидеть, если у них есть хозяин. Если нет, он является внутренним для сайта.

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

 
uri = URI.parse('http://my.example.com') 

uri.route_to('http://my.example.com/main.rbx?page=1').host # => nil 
uri.route_to('http://another.com/main.rbx?page=1').host # => "another.com" 

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

Вместо этого я бы использовал методы URI, чтобы избежать этих ложных срабатываний; Используйте route_to(), чтобы попытаться создать относительный путь к URL. Если результат имеет значение .host, то он является внешним.

+0

очень хороший ответ. Спасибо вам за это. – Radek

+0

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

1

используйте Uri метода, Линка:

page.links.each do |link| 
    next unless link.uri.host.match(/(www\.)?thissite\.com/) 
    process_page($agent.get(link.href)) 
    end 
+0

@ COdeJoust: он выглядит неплохо, но 'in' process_page ': undefined method 'url' для # (NoMethodError)' – Radek

+0

ok, it похоже, что метод на самом деле .uri, но иногда вы можете иметь относительный путь в веб-сервере, а затем я получаю 'undefined method 'match' для nil: NilClass (NoMethodError)', потому что нет хоста – Radek