Crea un ciclo che visita ogni link su un sito [chiuso]

0

Voglio creare un raschietto HTML in Ruby on Rails e voglio implementare una barra di avanzamento e un'abilità che riprenda da dove era stata interrotta se è stata interrotta durante lo scraping.

Penso che il modo migliore per farlo sia quello di creare una tabella di database con un record per ogni singola pagina, con una colonna booleana chiamata 'raschiato?'

Penso che il mio raschietto avrebbe due parti principali. La prima parte passerebbe attraverso l'intero sito, seguendo tutti i link e salvando i loro URL nella tabella, insieme a false per il loro attributo scraped? . Inoltre ripristinerebbe la sequenza pk del database, il che significa che la colonna id implicherebbe accuratamente quale numero il record è (più ne parlerò dopo!)

ActiveRecord::Base.connection.reset_pk_sequence!('pages')

La seconda parte passerebbe quindi attraverso questa tabella, visitando ciascun link e, una volta eseguita la scansione di quella pagina, cambierebbe il suo attributo scraped? a true.

Questa seconda parte inizierà con la prima pagina che non è stata ancora raschiata:

first_page = Page.where(:scraped? = false).first

La barra di avanzamento funzionerebbe secondo il seguente principio:

total_page = Page.count
done_pages = first_page.id # (the first result would always be 1 because the first part resets the sequence)
percentage = done_pages / total_pages * 100

In realtà non vedo perché questo non avrebbe funzionato, ma sono ancora molto vago su come il raschietto si aggiri e visita ogni singolo link su un sito web.

Quali sarebbero le tue idee su questo? Voglio solo alcuni suggerimenti prima di immergermi:

Come farebbe a sapere di non allontanarsi dal sito attuale? (Sto pensando a regex sull'URL per assicurarmi che contenga il dominio specificato prima di visitarlo)

Come non visiterebbe loop infiniti? Come un collegamento alla home page sulla home page? (Immagino che un condizionale farebbe il trucco qui):

if new_uri != current_uri
    visit new_uri
end

In che modo la prima parte andrebbe effettivamente a spidering, salvando un indice di ogni singolo link? Creando un array di ogni singolo link sulla pagina e poi iterandolo fino a trovare un uri che non esiste nel database? (questa è in realtà la mia più grande preoccupazione.)

Se quanto sopra è vero, come saprebbe quando fermarsi? Immagino che controllerebbe ogni new_link con i collegamenti esistenti nel database? Questo è solo un programma locale che verrà eseguito una volta, quindi non sono troppo preoccupato per le prestazioni qui, ma hai un'idea migliore di seguito:

if new_uri != current_uri # technically not necessary but it would save a few database interactions
    if Page.exists?( uri: new_uri) == false
        visit new_uri
    end
end
    
posta Crazy JIm 15.03.2014 - 18:32
fonte

1 risposta

2

In realtà è molto più difficile di quanto hai descritto:

  1. Alcuni collegamenti (diversi) possono fare riferimento alla stessa pagina. Considera /forum/index.html?topic=3&page=2 e /forum/index.html?page=2&topic=3 come un esempio banale (i parametri di richiesta sono scambiati). Quindi rilevare se la pagina viene sottoposta a scansione già richiederebbe di controllare il contenuto della pagina.
  2. I contenuti della pagina possono cambiare ad ogni richiesta. Considera "posted 1 minute ago" sul post del commento.
  3. Alcune pagine potrebbero essere inaccessibili per molte ragioni (quindi gli URL devono essere contrassegnati di conseguenza):
    • link è rotto
    • richiesta autorizzazione
    • la pagina
    • non esiste più
  4. Alcuni URL potrebbero essere "interni", ma in realtà reindirizzare ad altri siti: http://vk.com/away.php?to=http%3A%2F%2Fexample.com%2F
  5. Alcuni URL possono portare a file, non pagine HTML

Riassumendo, devi essere in grado di:

  • imposta "stati" sugli URL: "checked" / "not checked", "malformed", "access negato", "outside redirect", ecc. - potresti effettivamente utilizzare gli stati di risposta HTTP qui
  • memorizza il tipo di risposta MIME per distinguere le pagine HTML dai file scaricabili
  • rende le differenze tra i contenuti delle pagine, in modo che tu possa dire se due URL puntano alla stessa pagina. La semplice diffusione testuale probabilmente non funzionerà perché la struttura HTML deve essere rispettata. La definizione di "stessa pagina" può essere complicata e dipende da quanto di contenuto è diverso (ad esempio, le pagine sono considerate uguali se > 95% di testo in chiaro è uguale e la struttura HTML è la stessa)

Probabilmente è anche più complicato di quanto pensassi, perché non ho mai creato un crawler. La prima cosa da fare qui è trovare alcuni crawler esistenti e utilizzare uno di essi o esaminarli come esempi di come le cose dovrebbero funzionare. Scopri le gemme (se deve essere Ruby) come Mechanize per iniziare (l'ho trovato dopo 2 minuti su google, quindi google in profondità) .

    
risposta data 15.03.2014 - 20:54
fonte

Leggi altre domande sui tag