2010-03-14 8 views
10

J'ai un (un peu complexe) défi de grattage Web que je souhaite accomplir et aimerais pour une direction (à tout niveau que vous avez envie de partager) va ici:Comment puis-je utiliser R (packages Rcurl/XML?!) Pour gratter cette page Web?

Je voudrais passer en revue toutes les "pages d'espèces "présent dans ce lien:

http://gtrnadb.ucsc.edu/

donc, pour chacun d'eux, je vais aller à:

  1. Le lien de la page des espèces (par exemple: http://gtrnadb.ucsc.edu/Aero_pern/)
  2. Et puis à la « Structures secondaires » lien de la page (par exemple: http://gtrnadb.ucsc.edu/Aero_pern/Aero_pern-structs.html)

intérieur de ce lien que je souhaite supprimer les données de la page afin que je vais avoir une longue liste contenant ces données (par exemple):

chr.trna3 (1-77) Length: 77 bp 
Type: Ala Anticodon: CGC at 35-37 (35-37) Score: 93.45 
Seq: GGGCCGGTAGCTCAGCCtGGAAGAGCGCCGCCCTCGCACGGCGGAGGcCCCGGGTTCAAATCCCGGCCGGTCCACCA 
Str: >>>>>>>..>>>>.........<<<<.>>>>>.......<<<<<.....>>>>>.......<<<<<<<<<<<<.... 

où chaque ligne aura sa propre liste de (dans la liste pour chaque « ARNt » à l'intérieur de la liste pour chaque animal)

Je me souviens à venir à travers les paquets Rbordage et XML (en R) cela peut permettre une telle tâche. Mais je ne sais pas comment les utiliser. Donc ce que j'aimerais avoir est: 1. Quelques suggestions sur la façon de construire un tel code. 2. Et une recommandation sur la façon d'apprendre les connaissances nécessaires pour effectuer une telle tâche.

Merci pour toute aide,

Tal

+1

@Tal, une question, si je peux: est-ce légal? Et si oui, ne serait-il pas plus simple de demander à UCSC un accès régulier à sa base de données? –

+2

Salut Tal, essayez de les laisser tomber une ligne quand même. Vous pourriez les trouver assez accommodant. Ils peuvent même ne pas être conscients que les gens veulent utiliser les données comme vous le souhaitez. Peut-être qu'ils seront intéressés à fournir ce que vous voulez? – user246211

Répondre

17

Tal,

Vous pouvez utiliser R et le paquet XML pour ce faire, mais (putain) qui est un peu HTML mal formé que vous essayez d'analyser. En fait, dans la plupart des cas, vous voudriez utiliser la fonction readHTMLTable(), which is covered in this previous thread. Cependant, compte tenu de ce langage hideux, nous devrons utiliser le package RCurl pour extraire le code HTML brut et créer des fonctions personnalisées pour l'analyser.Ce problème comporte deux volets:

  1. obtenir tous les URLS du génome de la page Web de base (http://gtrnadb.ucsc.edu/) en utilisant la fonction getURLContent() dans le paquet RCurl et un peu de magie regex :-)
  2. Prenez ensuite la liste des URLS et grattez les données que vous recherchez, puis collez-les dans un data.frame.

Alors, va ici ...

library(RCurl) 

### 1) First task is to get all of the web links we will need ## 
base_url<-"http://gtrnadb.ucsc.edu/" 
base_html<-getURLContent(base_url)[[1]] 
links<-strsplit(base_html,"a href=")[[1]] 

get_data_url<-function(s) { 
    u_split1<-strsplit(s,"/")[[1]][1] 
    u_split2<-strsplit(u_split1,'\\"')[[1]][2] 
    ifelse(grep("[[:upper:]]",u_split2)==1 & length(strsplit(u_split2,"#")[[1]])<2,return(u_split2),return(NA)) 
} 

# Extract only those element that are relevant 
genomes<-unlist(lapply(links,get_data_url)) 
genomes<-genomes[which(is.na(genomes)==FALSE)] 

### 2) Now, scrape the genome data from all of those URLS ### 

# This requires two complementary functions that are designed specifically 
# for the UCSC website. The first parses the data from a -structs.html page 
# and the second collects that data in to a multi-dimensional list 
parse_genomes<-function(g) { 
    g_split1<-strsplit(g,"\n")[[1]] 
    g_split1<-g_split1[2:5] 
    # Pull all of the data and stick it in a list 
    g_split2<-strsplit(g_split1[1],"\t")[[1]] 
    ID<-g_split2[1]        # Sequence ID 
    LEN<-strsplit(g_split2[2],": ")[[1]][2]  # Length 
    g_split3<-strsplit(g_split1[2],"\t")[[1]] 
    TYPE<-strsplit(g_split3[1],": ")[[1]][2] # Type 
    AC<-strsplit(g_split3[2],": ")[[1]][2]  # Anticodon 
    SEQ<-strsplit(g_split1[3],": ")[[1]][2]  # ID 
    STR<-strsplit(g_split1[4],": ")[[1]][2]  # String 
    return(c(ID,LEN,TYPE,AC,SEQ,STR)) 
} 

# This will be a high dimensional list with all of the data, you can then manipulate as you like 
get_structs<-function(u) { 
    struct_url<-paste(base_url,u,"/",u,"-structs.html",sep="") 
    raw_data<-getURLContent(struct_url) 
    s_split1<-strsplit(raw_data,"<PRE>")[[1]] 
    all_data<-s_split1[seq(3,length(s_split1))] 
    data_list<-lapply(all_data,parse_genomes) 
    for (d in 1:length(data_list)) {data_list[[d]]<-append(data_list[[d]],u)} 
    return(data_list) 
} 

# Collect data, manipulate, and create data frame (with slight cleaning) 
genomes_list<-lapply(genomes[1:2],get_structs) # Limit to the first two genomes (Bdist & Spurp), a full scrape will take a LONG time 
genomes_rows<-unlist(genomes_list,recursive=FALSE) # The recursive=FALSE saves a lot of work, now we can just do a straigh forward manipulation 
genome_data<-t(sapply(genomes_rows,rbind)) 
colnames(genome_data)<-c("ID","LEN","TYPE","AC","SEQ","STR","NAME") 
genome_data<-as.data.frame(genome_data) 
genome_data<-subset(genome_data,ID!="</PRE>") # Some malformed web pages produce bad rows, but we can remove them 

head(genome_data) 

La trame de données résultant contient sept colonnes liées à chaque entrée du génome: ID, la longueur, le type, la séquence, la chaîne et le nom. La colonne de nom contient le génome de base, ce qui était ma meilleure estimation pour l'organisation des données. Voici ce qu'il ressemble:

head(genome_data) 
            ID LEN TYPE       AC                  SEQ 
1  Scaffold17302.trna1 (1426-1498) 73 bp Ala  AGC at 34-36 (1459-1461) AGGGAGCTAGCTCAGATGGTAGAGCGCTCGCTTAGCATGCGAGAGGtACCGGGATCGATGCCCGGGTTTTCCA 
2 Scaffold20851.trna5 (43038-43110) 73 bp Ala AGC at 34-36 (43071-43073) AGGGAGCTAGCTCAGATGGTAGAGCGCTCGCTTAGCATGCGAGAGGtACCGGGATCGATGCCCGGGTTCTCCA 
3 Scaffold20851.trna8 (45975-46047) 73 bp Ala AGC at 34-36 (46008-46010) TGGGAGCTAGCTCAGATGGTAGAGCGCTCGCTTAGCATGCGAGAGGtACCGGGATCGATGCCCGGGTTCTCCA 
4  Scaffold17302.trna2 (2514-2586) 73 bp Ala  AGC at 34-36 (2547-2549) GGGGAGCTAGCTCAGATGGTAGAGCGCTCGCTTAGCATGCGAGAGGtACAGGGATCGATGCCCGGGTTCTCCA 
5 Scaffold51754.trna5 (253637-253565) 73 bp Ala AGC at 34-36 (253604-253602) CGGGGGCTAGCTCAGATGGTAGAGCGCTCGCTTAGCATGCGAGAGGtACCGGGATCGATGCCCGGGTCCTCCA 
6  Scaffold17302.trna4 (6027-6099) 73 bp Ala  AGC at 34-36 (6060-6062) GGGGAGCTAGCTCAGATGGTAGAGCGCTCGCTTAGCATGCGAGAGGtACCGGGATCGATGCCCGAGTTCTCCA 
                     STR NAME 
1 .>>>>>>..>>>>........<<<<.>>>>>.......<<<<<.....>>>>>.......<<<<<<<<<<<.. Spurp 
2 .>>>>>>..>>>>........<<<<.>>>>>.......<<<<<.....>>>>>.......<<<<<<<<<<<.. Spurp 
3 .>>>>>>..>>>>........<<<<.>>>>>.......<<<<<.....>>>>>.......<<<<<<<<<<<.. Spurp 
4 >>>>>>>..>>>>........<<<<.>>>>>.......<<<<<.....>.>>>.......<<<.<<<<<<<<. Spurp 
5 .>>>>>>..>>>>........<<<<.>>>>>.......<<<<<.....>>>>>.......<<<<<<<<<<<.. Spurp 
6 >>>>>>>..>>>>........<<<<.>>>>>.......<<<<<......>>>>.......<<<<.<<<<<<<. Spurp 

J'espère que cela aide, et merci pour le petit défi amusant R dimanche après-midi!

+0

Ah, merci Tal. Je n'avais pas fait une recherche suffisamment approfondie des entrées possibles. Je suis content que vous ayez réussi à le faire fonctionner! – DrewConway

+0

L'aide de readHTMLtable donne une méthode pour les tables PRE. Quelque chose comme: u = "http://gtrnadb.ucsc.edu/Ppaci1/Ppaci1-structs.html"; h = htmlParse (u); p = getNodeSet (h, "// pre"); con = textConnection (xmlValue (p [[2]])); readLines (con, n = 4) [- 1] Peut aider. –

0

problème intéressant et conviennent que R est cool, mais en quelque sorte i trouver R être un peu lourd à cet égard. Il semble que je préfère d'abord obtenir les données sous forme de texte brut intermédiaire afin de pouvoir vérifier que les données sont correctes à chaque étape ... Si les données sont prêtes dans leur forme finale ou pour télécharger vos données quelque part RCurl est très utile.

Simplest à mon avis serait de (sur linux/unix/mac/ou Cygwin) miroir juste l'ensemble du site http://gtrnadb.ucsc.edu/ (en utilisant wget) et prendre les fichiers nommés / -structs.html, sed ou awk la données que vous souhaitez et le formater pour la lecture dans R.

Je suis sûr qu'il y aurait beaucoup d'autres façons aussi.

1

Je viens de l'essayer en utilisant Mozenda (http://www.mozenda.com). Après environ 10 minutes et j'avais un agent qui pouvait gratter les données que vous décrivez. Vous pouvez être en mesure d'obtenir toutes ces données simplement en utilisant leur essai gratuit. Coder est amusant, si vous avez le temps, mais il semble que vous ayez déjà une solution codée pour vous. Beau travail Drew.