Categorias
Artigos Python

Baixando metadados de artigos da API do PubMed

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.

Por Diego Mariano

Doutor em Bioinformática pela Universidade Federal de Minas Gerais com atuação na área de ciência de dados e aprendizado de máquina aplicados ao aperfeiçoamento de enzimas usadas na produção de biocombustíveis. Mestre em Bioinformática, também pela UFMG, atuando na área de desenvolvimento de sistemas Web para montagem de genomas. Atualmente realiza estágio pós-doutoral no Departamento de Ciência da Computação da UFMG com foco em desenvolvimento de sistemas Web para Bioinformática, análise exploratória e visualização de dados. Tem conhecimentos nas linguagens: PHP, JavaScript, Python, R, Perl, HTML, CSS e SQL.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.

error

Compartilhe este post!

Facebook
YouTube
LinkedIn
Instagram