2014-08-27 2 views
0

J'ai créé un script Ruby Scraper Web à l'aide d'Open-URI et de Nokogiri. Je suis plutôt novice, mais tout fonctionne pour quelques sites Web dont j'ai besoin d'extraire des données qui ont des URL complètes dans la source, à l'exception d'une URL qui utilise des URL relatives.Ruby - Ouverture d'une URL absolue à partir d'un parent

Ce que fait le script, c'est d'ouvrir la page, de construire un tableau de pages à ouvrir puis de parcourir et d'extraire les données du css (pas de xpath).

Comment forcer le script à utiliser son URL complète dans le cas où ils sont par rapport, il a été me casser les pieds pendant un certain temps et je ne peux pas sembler le faire fonctionner

Dans mon cas, je pense J'ai besoin d'ajouter quelque chose au point où il pousse l'URL, quelqu'un pourrait-il me diriger dans la bonne direction? Ce serait énormément apprécié! Merci!

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

Vous pouvez utiliser une regex pour vérifier une URL complète, quelque chose comme/^ [\ w] *: \/\ // - si elle correspond puis préfixer l'URL racine Se souvenir de la subtilité de '/' au début d'une URL relative indiquant qu'elle commence à la racine du chemin après le serveur, par opposition aux liens relatifs commençant sans barre oblique, qui correspondent au répertoire de la page en cours. J'écrirais une réponse mais j'aurais besoin de plus de connaissances sur les variables disponibles pour moi. (L'URL complète actuelle et le chemin de la page en cours, principalement.) –

+0

Modifié pour ajouter des variables! – James

Répondre

0

tl; dr: réponse courte en bas.

OK, en supposant que vous avez une variable de classe appelée @url contenant l'URL complète de la page en cours:

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 

vous pouvez appeler:

links_array.push full_url(url, @url) 

Vous pouvez mettre la méthode dans la même classe ou dans une classe d'aide quelque part. Il utilise la bibliothèque Ruby URI pour trouver les parties pertinentes de l'URL complète, puis en construit une nouvelle à partir du chemin relatif.

Si le chemin relatif commence par '/', il devrait arriver juste après l'hôte. Si elle ne commence pas par un «/», elle doit se trouver dans le même répertoire virtuel que la page en cours. Ainsi, si la page en cours est:

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

et le chemin relatif est: cependant,

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

si le chemin relatif est::

ddd 

alors la sortie devrait être

/ddd 

alors la sortie devrait être:

http://www.host.com/ddd 

Le code:

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

prend le chemin de l'URL complète, elle se déchire '/' donnant un tableau (['aaa','bbb', 'ccc']), puis supprime le dernier élément. (['aaa','bbb']). La sélection supprime tous les éléments vides, puis la jointure se resserre.("aaa/bbb")

OU

vous pourriez faire la façon ennuyeuse:

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" 

donné votre code:

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

je serais récrire comme:

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 

Note: S D'un point de vue tylistique, les blocs multilignes doivent utiliser do/end plutôt que {}. Les retraits devraient être deux espaces. Il ne devrait pas y avoir d'espaces juste entre parenthèses. L'opérateur < < est favorisé par poussée. Toujours utiliser & & dans des conditions plutôt que and, ce qui a une priorité beaucoup plus faible et peut entraîner des problèmes. Voir le guide de style Github:

https://github.com/styleguide/ruby

Les puts y sont basées sur vos commentaires, nous l'espérons vous aider à comprendre pourquoi votre tableau ne se comporte pas. Comme il se doit, en fonction du code que vous avez ajouté. Je préférerais utiliser le joyau du débogueur. (Ou byebug si vous êtes sur Ruby 2.x)

+0

Merci pour votre réponse, j'ai ajouté votre code et ajouté une variable @url qui a entraîné l'arrêt de l'erreur No tel fichier ou répertoire, qui je pense indique qu'il met les deux valeurs ensemble, mais il ne semble pas être l'ouverture le tableau d'URL dont je vais avoir besoin, je vais essayer de résoudre ce problème et revenir pour confirmer que votre résolution fonctionne! Merci! – James

+0

Vérifiez la fin éditée de la réponse, qui montre une solution beaucoup plus simple et plus propre. –

+0

Inspiré par votre dernier commentaire, je suis venu avec cette ' @full_url = recueil HSC URI.join (PAGE_URL, url) .to_s met @full_url links_array.push @full_url fin } ' code ' Il se connecte correctement (le put est en train d'imprimer les URL complètes) mais il ne semble pas qu'il passe au tableau. Pouvez-vous voir des erreurs ici qui pourraient expliquer cela? – James