2016-12-06 3 views
1

Ich habe ein Skript mit dem Python-Modul BeautifulSoup geschrieben, um das XML von einer Webseite zu bekommen. Diese Webseite enthält Informationen, die ein Projekt beschreiben, das genomische Daten verwendet, und ich möchte alle PUBMED-IDs (eindeutige ID-Nummern für die Publikationen, die aus diesem Projekt stammen) extrahieren. Jede PUBMED ID ist eine 8-stellige Nummer.Python, suchen Sie nach Text in der Zeile direkt unter einer bekannten Zeichenfolge?

Ich habe zwei verschiedene Methoden ausprobiert, um die PUBMED IDs zu extrahieren, aber es gibt Probleme mit beiden. Zum einen habe ich diesen Code die komplette XML zu extrahieren:

url = 'http://www.ebi.ac.uk/ena/data/view/PRJEB2357&display=xml' 
project_page = urlopen(url) 
soup = BeautifulSoup(project_page, "html.parser") 
print soup 

Die Ausgabe dieses Befehls wie dies ein wenig aussieht:

<db>PUBMED</db> 
<id>25101644</id> 
</xref_link> 
</project_link> 
<project_link> 
<xref_link> 
<db>PUBMED</db> 
<id>24509479</id> 

(offensichtlich nicht die Gesamtheit des xml ist, nur die Abschnitt, der für mich relevant ist).

Das BeautifulSoup-Modul enthält eine Reihe von Befehlen, die diese Suppe nach Text von Interesse durchsuchen, aber soweit ich sagen kann, nehmen alle entweder das Tag oder den gesuchten Text als Eingabe. Ich kann keine von diesen hier verwenden, da es mehrere Textsegmente außer der PUBMED-ID auf dieser Seite gibt, die das gleiche XML-Tag haben (<id>), und ich kann eindeutig nicht nach der PUBMED-ID mit dem Text I suchen Ich weiß nicht, was es ist!

Die zweite Methode, die ich versucht wurde, den Druck nur den Text aus dem XML-Code verwenden:

url = 'http://www.ebi.ac.uk/ena/data/view/PRJEB2357&display=xml' 
project_page = urlopen(url) 
soup = BeautifulSoup(project_page, "html.parser") 
text = soup.text 
print text 

wie diese Diesmal sieht die Ausgabe:

PUBMED 
25101644 




PUBMED 
24509479 

ich ein paar Ideen hatte bei dieser Punkt. Erstens könnte das python re-Modul (Regex in früheren Versionen von Python) verwendet werden, um nach dem Ausdruck zu suchen, aber wiederum erfordern alle mir bekannten re-Befehle mindestens einen Teil des gesuchten Musters als Eingabe, also glaube ich das nicht Dies allein ist eine Option. Zweitens habe ich versucht, so etwas zu tun:

url = 'http://www.ebi.ac.uk/ena/data/view/PRJEB2357&display=xml' 
project_page = urlopen(url) 
soup2 = BeautifulSoup(project_page, "html.parser") 
text = soup2.text 
text = text.replace('\n', ' ').replace(' ', '') #removes all spaces and linebreaks 
PMID = re.findall('PUBMED........', text, flags = 0) 
print PMID 

Dieser diesen Ausgang gibt:

[u'PUBMED25101644', u'PUBMED24509479'] 

diese in einen String umgewandelt werden also theoretisch könnte und ich nur die entsprechenden 8-stellige Zahlen ausgeschnitten, aber Dies wird sehr hacky und ich möchte dieses Skript auf den Webseiten für mehrere tausend Projekte mehrmals ausführen und die Anzahl der PUBMED IDs für jedes Projekt variiert, so dass diese Methode sich nicht sehr gut für die Automatisierung eignet.

Was ich will ist eine Methode der Suche nach jeder Instanz des Wortes "PUBMED", entweder in der rohen Suppe oder im Text und Extrahieren nur der PUBMED ID, die in der nächsten Zeile sein wird. Hat jemand irgendwelche Vorschläge, wie man das macht?

Antwort

0

Sie direkt den Blick hinter in den regulären Ausdruck verwenden können. Wenn der Text ist

print text 
PUBMED 
25101644 




PUBMED 
24509479 

Durch die Verwendung des

>>> re.findall('(?<=PUBMED\n).+',text) 
['25101644', '24509479'] 

Wenn Sie nur die Ziffern erhalten möchten, dass die bekannte Zeichenfolge ersetzen .+ mit [\d]+ folgen und es würde nur die Ziffern wählen.

Hoffe, das hilft.

+0

Danke, das funktioniert wirklich gut abgesehen von dem allerletzten Bit, meine Ausgabe sieht so aus: [u'25101644 ', u'24509479'] auch wenn ich die Option [\ d] + ... –

+0

Das ist, weil Der Text ist eine Unicode-Zeichenfolge. Sie können eine weitere Zeile wie diese versuchen, um eine Liste von Ganzzahlen zu erhalten. –

+0

results = [int (Element) für Element in re.findall ('(? <= PUBMED \ n). +', Text)] –

1

Suche alle Vorkommen von PUBMED und erhalten die next siblings:

[pubmed.find_next_sibling("ID").get_text() 
for pubmed in soup.find_all("DB", text="PUBMED")] 

Oder eine machen search function:

search = lambda tag: tag.name == "ID" and tag.find_previous_sibling("DB", text="PUBMED") 
print([pubmed.get_text() for pubmed in soup.find_all(search)]) 

Beachten Sie, dass xml Parser verwenden sollten und nicht die html.parser:

soup = BeautifulSoup(project_page, "xml") 

DEMO:

In [1]: from urllib2 import urlopen 

In [2]: from bs4 import BeautifulSoup 

In [3]: url = 'http://www.ebi.ac.uk/ena/data/view/PRJEB2357&display=xml' 

In [4]: project_page = urlopen(url) 

In [5]: soup = BeautifulSoup(project_page, "xml") 

In [6]: [pubmed.find_next_sibling("ID").get_text() 
    ...: for pubmed in soup.find_all("DB", text="PUBMED")] 
Out[6]: [u'25101644', u'24509479'] 

In [7]: search = lambda tag: tag.name == "ID" and tag.find_previous_sibling("DB", text="PUBMED") 

In [8]: [pubmed.get_text() for pubmed in soup.find_all(search)] 
Out[8]: [u'25101644', u'24509479'] 
0

können Sie db finden und dann seine erste Geschwister bekommen

data = '''<db>PUBMED</db> 
<id>25101644</id> 
</xref_link> 
</project_link> 
<project_link> 
<xref_link> 
<db>PUBMED</db> 
<id>24509479</id>''' 

from bs4 import BeautifulSoup 
soup = BeautifulSoup(data, "html.parser") 
#print(soup) 

for x in soup.find_all('db'): 
    print(x.text, x.fetchNextSiblings()[0].text) 

Ergebnis

PUBMED 25101644 
PUBMED 24509479 
Verwandte Themen