Neste tutorial, vou mostrar como podemos usar Python para baixar metadados de artigos da API do PubMed.
Antes de mais nada, crie uma conta no My NCBI, vá nas configurações e crie uma chave de API. Isso permitirá que você faça até 10 requisições por segundo.
Passo 1. Obtendo o PubMed-ID
Se você tem o título de um artigo, mas não tem um identificador único, você pode realizar uma consulta pelo PubMed-ID. Apenas com esse identificador, você conseguirá outros dados do artigo em questão.
Você pode obter isso por meio de uma requisição GET similar a feita ao clicar neste link. Veja como podemos personalizá-la:
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi
- ?db=pubmed
- Base de dados usada na busca.
- &retmode=json
- Formato de saída (pode ser xml ou json).
- &retmax=1
- Quantidade de itens exibidos (aqui é retornado apenas 1).
- &term=Título do artigo
- Digite o título do artigo que se deseja buscar
- &api_key=digite aqui sua chave de API (opcional)
- Inclua a chave de API aqui.
Resultado esperado
No formato XML, você poderá obter o ID na seguinte posição:
<esearchresult>
<idlist>
12345678
</idlist>
</esearchresult>
No formato JSON, você pode obtê-lo nessa posição:
pubmed_id = resultado['esearchresult']['idlist'][0]
import requests
import csv
import json
import time
# pubmed &api_key=
api_pubmed = "xyz"
# INPUT: título do artigo
# OUTPUT (desejado): abstract
# Passo 1. obtendo o pubmed ID
url_pubmed_id = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&retmode=json&retmax=1&api_key="+api_pubmed+"&term="
# Passo 2. obtendo o abstract
url_get_abstract = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&rettype=abstract&api_key="+api_pubmed+"&id="
i = 0
pubmed_id = {}
w_pid = open('pubmed_ids.tsv','a+')
# entrada: um arquivo CSV com os títulos de artigos (1 por linha)
with open('titulos_artigos.csv', newline='') as csvfile:
tabela = csv.reader(csvfile, delimiter=';', quotechar='|')
for linha in tabela:
i+=1
if i < 0: # CONTINUAR A PARTIR DA LINHA (caso o script falhe)
continue
titulo = linha[0].strip()
with open('tmp.json','w') as w:
r = requests.get(url_pubmed_id+titulo)
w.write(str(r.text))
with open('tmp.json') as meu_json:
x = json.load(meu_json)
try:
pubmed_id_atual = x['esearchresult']['idlist'][0]
pubmed_id[pubmed_id_atual] = titulo
w_pid.write(pubmed_id_atual+"\t"+titulo+"\n")
except:
w_pid.write("-\t"+titulo+"\n")
if i%10==0:
print(i)
time.sleep(1)
with open('i.txt','a+') as backup:
backup.write(str(i)+',')
w_pid.close()
w_pid = open('pubmed_ids.tsv','a+')
Passo 2. Obtendo o resumo (abstract)
Já com o PubMed-ID do artigo em questão obtido, agora vamos obter o abstract e outros metadados, como título do artigo, autores, dentre outras coisas. Observe este exemplo.
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi
- ?db=pubmed
- &id=12345678
- &rettype=abstract
- &api_key=xyz
Resultado esperado (em XML)
<PubmedArticleSet>
<PubmedArticle>
<MedlineCitation>
<Article>
<Abstract>
<AbstractText>
Aqui vai o abstract
</AbstractText>
</Abstract>
<ELocationID EIdType="doi">DOI</ELocationID>
<Journal>
<Title>Pharmaceutics</Title>
<ISSN IssnType="Print"> 1234-5678 </ISSN>
</Journal>
<ArticleTitle> XYZ </ArticleTitle>
</Article>
</MedlineCitation>
</PubmedArticle>
</PubmedArticleSet>
A segunda etapa será um pouco mais complexa, pois vários trechos da consulta podem retornar exceções. O código abaixo é uma versão inicial que tenta pegar os artigos e verificar se os títulso correspondem ao título indicado (e assim evitar falsos-positivos).
import requests
import csv
import json
import time
import xml.etree.ElementTree as ET
# pubmed &api_key=
api_pubmed = ""
# INPUT: título do artigo
# OUTPUT (desejado): abstract
# Passo 1. obtendo o pubmed ID
url_pubmed_id = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&retmode=json&retmax=1&api_key="+api_pubmed+"&term="
# Passo 2. obtendo o abstract
url_get_abstract = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&rettype=abstract&api_key="+api_pubmed+"&id="
i = 0
pubmed_id = {}
w_pid = open('pubmed_ids.tsv','a+')
with open('categorias/titulos_artigos.csv', newline='') as csvfile:
tabela = csv.reader(csvfile, delimiter=';', quotechar='|')
for linha in tabela:
i+=1
if i < 2149: # CONTINUAR A PARTIR DA LINHA (caso o script falhe)
continue
titulo = linha[0].strip()
with open('tmp.json','w') as w:
r = requests.get(url_pubmed_id+titulo)
w.write(str(r.text))
with open('tmp.json') as meu_json:
x = json.load(meu_json)
try:
pubmed_id_atual = x['esearchresult']['idlist'][0]
pubmed_id[pubmed_id_atual] = titulo
w_pid.write(pubmed_id_atual+"\t"+titulo+"\n")
except:
w_pid.write("-\t"+titulo+"\n")
if i%10==0:
print(i,'/ 2147')
time.sleep(1)
with open('i.txt','a+') as backup:
backup.write(str(i)+',')
w_pid.close()
w_pid = open('pubmed_ids.tsv','a+')
w_pid.close()
# PARTE 2 - ABSTRACT
cont = 0
w = open('saida.csv','a+')
with open('pubmed_ids.tsv') as pid:
tabela = csv.reader(pid, delimiter='\t', quotechar='|')
for linha in tabela:
cont+=1
if cont%10==0:
print(cont)
if cont < 1790: # CONTINUAR A PARTIR DA LINHA (caso o script falhe) 1790 e 1420
continue
pubmed_id = linha[0]
titulo = linha[1]
if pubmed_id != '-':
r = requests.get(url_get_abstract+pubmed_id)
# print(r.text)
tree = ET.ElementTree(ET.fromstring(r.text))
root = tree.getroot()
try:
for a in root.findall("./PubmedArticle/MedlineCitation/Article/ArticleTitle"):
titulo_2 = a.text
# print(titulo, "\n", titulo_2, end="\n\n")
except:
titulo_2 = '-'
try:
for a in root.findall("./PubmedArticle/MedlineCitation/Article/Journal/ISSN"):
issn = a.text
# print(issn)
except:
issn = '-'
try:
for a in root.findall("./PubmedArticle/MedlineCitation/Article/Journal/Title"):
journal = a.text
# print(journal)
except:
journal = '-'
try:
for a in root.findall("./PubmedArticle/MedlineCitation/Article/ELocationID"):
doi = a.text
except:
doi = '-'
try:
for a in root.findall("./PubmedArticle/MedlineCitation/Article/Abstract/AbstractText"):
abstract = a.text
abstract = abstract.replace('\n','')
abstract = abstract.replace('\t','')
# print(abstract)
except:
abstract = '-'
tmp_titulo_1 = titulo.split()
try:
tmp_titulo_2 = titulo_2.split()
except:
tmp_titulo_2 = ['-']
tamanho = len(tmp_titulo_1)
match = 0
for i in tmp_titulo_1:
for j in tmp_titulo_2:
if i.upper().replace('.','') == j.upper().replace('.',''):
match += 1
# print('- ',titulo, '\n-',titulo_2)
# print(match, '/', tamanho,'\n')
if match/tamanho > 0.8:
# print('- ',titulo, '\n-',titulo_2,'\n')
try:
w.write(pubmed_id+"\t"+titulo+"\t"+ titulo_2+"\t"+ issn+ "\t"+journal+"\t"+doi+"\t"+abstract+"\n")
except:
print(titulo, match, tamanho)
Como saída, teremos o seguinte arquivo:
pubmed_id titulo titulo_checagem issn journal doi abstract
34311528 Efficacy of propolis as an adjunct treatment for hospitalized COVID-19 patients: a randomized, controlled clinical trial. Efficacy of Brazilian green propolis (EPP-AF®) as an adjunct treatment for hospitalized COVID-19 patients: A randomized, controlled clinical trial. 1950-6007 Biomedicine & pharmacotherapy = Biomedecine & pharmacotherapie 10.1016/j.biopha.2021.111526 Addition of propolis to the standard care procedures resulted in clinical benefits for the hospitalized COVID-19 patients, especially evidenced by a reduction in the length of hospital stay. Consequently, we conclude that propolis can reduce the impact of COVID-19.
33573699 Safety and Effectiveness of High-Dose Vitamin C in Patients with COVID-19 Safety and effectiveness of high-dose vitamin C in patients with COVID-19: a randomized open-label clinical trial. 2047-783X European journal of medical research 10.1186/s40001-021-00490-1 We did not find significantly better outcomes in the group who were treated with HDIVC in addition to the main treatment regimen at discharge. Trial registration irct.ir (IRCT20200411047025N1), April 14, 2020.