Cet article est une note personnelle sur la façon d'utiliser python pour lire les données de la littérature (format xml) qui ont été capturées lors d'une recherche sur Pubmed.
Je vous serais reconnaissant de bien vouloir souligner les points que vous avez remarqués.
Une donnée ressemble à ce qui suit. En fait, je souhaite traiter plusieurs données, mais je vais d'abord permettre de les traiter une par une.
001.xml
<PubmedArticle>
<MedlineCitation Status="Publisher" Owner="NLM">
<PMID Version="1">12345678</PMID>
<DateRevised>
<Year>2020</Year>
<Month>03</Month>
<Day>27</Day>
</DateRevised>
<Article PubModel="Print-Electronic">
<Journal>
<ISSN IssnType="Electronic">1873-3700</ISSN>
<JournalIssue CitedMedium="Internet">
<PubDate>
<Year>2020</Year>
<Month>Mar</Month>
</PubDate>
</JournalIssue>
<Title>Journal of XXX</Title>
</Journal>
<ArticleTitle>Identification of XXX.</ArticleTitle>
<AuthorList CompleteYN="Y">
<Author ValidYN="Y">
<LastName>Sendai</LastName>
<ForeName>Shiro</ForeName>
<Initials>S</Initials>
<AffiliationInfo>
<Affiliation>Sendai, Japan.</Affiliation>
</AffiliationInfo>
</Author>
<Author ValidYN="Y">
<LastName>Tohoku</LastName>
<ForeName>Taro</ForeName>
<Initials>T</Initials>
<AffiliationInfo>
<Affiliation>Miyagi, Japan.</Affiliation>
</AffiliationInfo>
</Author>
</AuthorList>
<Language>eng</Language>
<PublicationTypeList>
<PublicationType UI="D016428">Journal Article</PublicationType>
</PublicationTypeList>
<ArticleDate DateType="Electronic">
<Year>2020</Year>
<Month>03</Month>
<Day>23</Day>
</ArticleDate>
</Article>
<CitationSubset>IM</CitationSubset>
</MedlineCitation>
<PubmedData>
<PublicationStatus>aheadofprint</PublicationStatus>
<ArticleIdList>
<ArticleId IdType="pubmed">32213359</ArticleId>
<ArticleId IdType="pii">S0031-9422(19)30971-9</ArticleId>
<ArticleId IdType="doi">10.1016/j.phytochem.2020.112349</ArticleId>
</ArticleIdList>
</PubmedData>
</PubmedArticle>
Chargez la bibliothèque pour lire xml.
001.py
import xml.etree.ElementTree as ET
Lisez les données XML du fichier. Il semble que plusieurs données soient alignées avec deux sauts de ligne, alors divisez-les en une liste.
002.py
test_data = open("./xxxx/pubmed.xml", "r")
contents = test_data.read()
records = contents.split('\n\n')
Les premières données du document (enregistrements [0]) sont lues par ET.fromstring () et stockées dans la racine de la variable. Si vous regardez root avec type (), vous verrez que c'est un objet Element.
003.py
root = ET.fromstring(records[0])
type(root)
#<class 'xml.etree.ElementTree.Element'>
Vous pouvez vérifier la balise avec root.tag. Je vais vérifier.
004.py
root.tag
#'PubmedArticle'
En gros, une donnée a la forme suivante. J'ai pu accéder à la balise la plus externe avec root.tag.
002.xml
<PubmedArticle>
<MedlineCitation>
</MedlineCitation>
<PubmedData>
</PubmedData>
</PubmedArticle>
À l'intérieur de \ <PubmedArticle > se trouvent deux éléments (MedlineCitation et PubmedData), auxquels il est possible d'accéder à l'aide d'indices. Accédez en utilisant des indices et recherchez le type plus loin.
005.py
root[0]
#<Element 'MedlineCitation' at 0x10a9d5b38>
type(root[0])
#<class 'xml.etree.ElementTree.Element'>
root[1]
#<Element 'PubmedData' at 0x10aa78868>
type(root[1])
#<class 'xml.etree.ElementTree.Element'>
Vous pouvez voir que les deux sont des objets Element.
En bref, il semble que tous les nœuds soient des objets Element. Les objets élément peuvent être itérés et les nœuds enfants peuvent être récupérés et traités un par un.
for i in root:
print(i.tag)
Les balises d'élément peuvent être recherchées dans .tag, et .attrib peut rechercher les attributs et les valeurs d'attribut attachés à cette balise.
root[0].tag
#'MedlineCitation'
root[0].attrib
#{'Status': 'Publisher', 'Owner': 'NLM'}
# root[0]La zone autour de l'étiquette est la suivante.
# <MedlineCitation Status="Publisher" Owner="NLM">
type(root[0].attrib)
#<class 'dict'> #Classe de dictionnaire
Il y en aura probablement trois. Dans chaque cas, vous pouvez spécifier une ou plusieurs balises. Mettez la balise entière entre guillemets et, lorsque vous spécifiez plusieurs balises, séparez les balises par une barre oblique.
Si c'est 1, l'objet Element est retourné, s'il vaut 2, la liste des objets Element est retournée, et si c'est 3, c'est un objet pour l'itération? Sera retourné. Je vais vérifier.
root.find('MedlineCitation/DateRevised/Year')
#<Element 'Year' at 0x10a9f8ae8>
root.findall('MedlineCitation')
#[<Element 'MedlineCitation' at 0x10a9d5b38>]
root.iter('Author')
#<_elementtree._element_iterator object at 0x10aa65990>
#Répétons avec l'instruction for.
for i in root.iter('Author'):
print(i)
#<Element 'Author' at 0x10aa6e9f8>
#<Element 'Author' at 0x10aa6ec28>
Il semble que findall () ne regarde que les nœuds enfants de l'objet Element, et iter () regarde tous les nœuds enfants, nœuds petits-enfants, nœuds arrière-petits-enfants ... de l'objet Element.
L'objet Element a deux valeurs. Valeur d'attribut et données textuelles. Les valeurs d'attribut peuvent être obtenues avec .get ('* nom de propriété ') pour les objets Element. Sinon, .attrib [' nom de la propriété *'] semble convenir.
#.get()Ou
root.find('MedlineCitation').get('Status')
#'Publisher'
#.attrib()Ou
root.find('MedlineCitation').attrib['Status']
#'Publisher'
Vous pouvez également obtenir des données texte en utilisant .text pour l'objet Element.
Les données de texte ici sont la partie entourée de balises, 2020 dans l'exemple ci-dessous. <Year>2020</Year>
Essayez d'obtenir la valeur en spécifiant le chemin vers l'objet Element avec find ().
root.find('MedlineCitation/Article/Journal/JournalIssue/PubDate/Year').text
#'2020'
Pour obtenir des informations sur plusieurs auteurs, parcourez la liste obtenue avec findall ().
Corrigé en tenant compte des affiliations multiples d'auteurs (31 mars 2020).
for x in root.findall('MedlineCitation/Article/AuthorList/Author'):
x.find('LastName').text #Nom de l'auteur
x.find('ForeName').text #Le nom de l'auteur
for y in x.findall('AffiliationInfo'):
y.find('Affiliation').text
Le doi (identifiant de document) est décrit dans la balise ELocationID, mais la balise ELocationID a des valeurs d'attribut, et il est nécessaire d'obtenir les données texte dans le cas de EIdType = "doi".
for x in root.findall('MedlineCitation/Article/ELocationID'):
if(x.get('EIdType') == 'doi'):
x.text
Il est nécessaire de distinguer si l'enregistrement est une revue ou un article de revue, qui est décrit dans le type de publication. Cependant, il existe généralement plusieurs types de publication, et si l'un d'entre eux a une valeur de révision, il semble que ce soit une révision.
Par exemple, si vous regardez l'enregistrement de révision, il ressemble à ceci:
.xml
<PublicationTypeList>
<PublicationType UI="D016428">Journal Article</PublicationType>
<PublicationType UI="D016454">Review</PublicationType>
<PublicationType UI="D013485">Research Support, Non-U.S. Gov't</PublicationType>
</PublicationTypeList>
Donc, qu'il s'agisse d'un examen ou non, c'est
isReview = False
for x in root.findall('MedlineCitation/Article/PublicationTypeList'):
if (x.text == 'Review'):
isReview = TRUE
Je pense que c'est bien de le faire.
Pour résumer ce qui précède, y compris d'autres informations que vous souhaiterez peut-être acquérir
import xml.etree.ElementTree as ET
test_data = open("./pubmed.xml", "r")
contents = test_data.read()
records = contents.split('\n\n')
root = ET.fromstring(records[0])#Pour le moment, seul le premier cas.
#Informations sur l'auteur
for x in root.findall('MedlineCitation/Article/AuthorList/Author'):
x.find('LastName').text #Nom de l'auteur
x.find('ForeName').text #Le nom de l'auteur
for y in x.findall('AffiliationInfo'):
y.find('Affiliation').text#Fixé.
#Juger s'il s'agit d'un examen
isReview = False
for x in root.findall('MedlineCitation/Article/PublicationTypeList'):
if (x.text == 'Review'):
isReview = TRUE
# doi
for x in root.findall('MedlineCitation/Article/ELocationID'):
if(x.get('EIdType') == 'doi'):
x.text
#PMID
root.find('MedlineCitation/PMID').text
#Titre du papier
root.find('MedlineCitation/Article/ArticleTitle').text
#Nom du journal
root.find('MedlineCitation/Article/Journal/Title').text
#Année de publication
root.find('MedlineCitation/Article/Journal/JournalIssue/PubDate/Year').text
#Mois de publication
root.find('MedlineCitation/Article/Journal/JournalIssue/PubDate/Month').text
#Langue
root.find('MedlineCitation/Article/Language').text
Je pense que cela devrait être fait. Dans le code ci-dessus, il n'y a qu'un seul processus,
for record in records:
root = ET.fromstring(record)
#Décrivez le processus
Vous devriez le faire comme.
Maintenant, si vous avez des données xml, vous pouvez extraire les informations nécessaires à la fois. Tout ce que vous avez à faire est de réfléchir à la façon de le façonner.
Vous savez maintenant comment gérer les données XML.
Recommended Posts