2013-07-01 23 views
7

私はPubMed IDと一緒にPubMedエントリのリストを持っています。私は入力としてPubMed ID番号を受け入れ、PubMedのWebサイトから要約を取得するPythonスクリプトを作成するか、Pythonを使用したいと思います。Pythonを使用してPubMedからデータを取得する

これまでのところ、私はNCBI EutilitiesとimporturlライブラリをPythonで見たことがありますが、どのようにしてテンプレートを書くべきか分かりません。

何か指摘します。

ありがとう、

答えて

3

うわーを、私はちょうど一週間ほど前、同様のプロジェクトに自分自身を働いていました!

編集:私は最近、BeautifulSoupを利用するようにコードを更新しました。私はそれのために私自身のvirtualenvを持っていますが、あなたはpipでそれをインストールすることができます。

私のプログラムは、pubmed ID、DOI、またはpubmed IDおよび/またはDOIの行のテキストファイルを取得し、記事に関する情報を取得します。簡単に要約を取得するために、独自のニーズに合わせて微調整することができますが、ここに私のコードは次のとおりです。

import re 
import sys 
import traceback 
from bs4 import BeautifulSoup 
import requests 

class PubMedObject(object): 
    soup = None 
    url = None 

    # pmid is a PubMed ID 
    # url is the url of the PubMed web page 
    # search_term is the string used in the search box on the PubMed website 
    def __init__(self, pmid=None, url='', search_term=''): 
     if pmid: 
      pmid = pmid.strip() 
      url = "http://www.ncbi.nlm.nih.gov/pubmed/%s" % pmid 
     if search_term: 
      url = "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s" % search_term 
     page = requests.get(url).text 
     self.soup = BeautifulSoup(page, "html.parser") 

     # set the url to be the fixed one with the PubMedID instead of the search_term 
     if search_term: 
      try: 
       url = "http://www.ncbi.nlm.nih.gov/pubmed/%s" % self.soup.find("dl",class_="rprtid").find("dd").text 
      except AttributeError as e: # NoneType has no find method 
       print("Error on search_term=%s" % search_term) 
     self.url = url 

    def get_title(self): 
     return self.soup.find(class_="abstract").find("h1").text 

    #auths is the string that has the list of authors to return 
    def get_authors(self): 
     result = [] 
     author_list = [a.text for a in self.soup.find(class_="auths").findAll("a")] 
     for author in author_list: 
      lname, remainder = author.rsplit(' ', 1) 
      #add periods after each letter in the first name 
      fname = ".".join(remainder) + "." 
      result.append(lname + ', ' + fname) 

     return ', '.join(result) 

    def get_citation(self): 
     return self.soup.find(class_="cit").text 

    def get_external_url(self): 
     url = None 
     doi_string = self.soup.find(text=re.compile("doi:")) 
     if doi_string: 
      doi = doi_string.split("doi:")[-1].strip().split(" ")[0][:-1] 
      if doi: 
       url = "http://dx.doi.org/%s" % doi 
     else: 
      doi_string = self.soup.find(class_="portlet") 
      if doi_string: 
       doi_string = doi_string.find("a")['href'] 
       if doi_string: 
        return doi_string 

     return url or self.url 

    def render(self): 
     template_text = '' 
     with open('template.html','r') as template_file: 
      template_text = template_file.read() 

     try: 
      template_text = template_text.replace("{{ external_url }}", self.get_external_url()) 
      template_text = template_text.replace("{{ citation }}", self.get_citation()) 
      template_text = template_text.replace("{{ title }}", self.get_title()) 
      template_text = template_text.replace("{{ authors }}", self.get_authors()) 
      template_text = template_text.replace("{{ error }}", '') 
     except AttributeError as e: 
      template_text = template_text.replace("{{ external_url }}", '') 
      template_text = template_text.replace("{{ citation }}", '') 
      template_text = template_text.replace("{{ title }}", '') 
      template_text = template_text.replace("{{ authors }}", '') 
      template_text = template_text.replace("{{ error }}", '<!-- Error -->') 

     return template_text.encode('utf8') 

def start_table(f): 
    f.write('\t\t\t\t\t\t\t\t\t<div class="resourcesTable">\n'); 
    f.write('\t\t\t\t\t\t\t\t\t\t<table border="0" cellspacing="0" cellpadding="0">\n'); 

def end_table(f): 
    f.write('\t\t\t\t\t\t\t\t\t\t</table>\n'); 
    f.write('\t\t\t\t\t\t\t\t\t</div>\n'); 

def start_accordion(f): 
    f.write('\t\t\t\t\t\t\t\t\t<div class="accordion">\n'); 

def end_accordion(f): 
    f.write('\t\t\t\t\t\t\t\t\t</div>\n'); 

def main(args): 
    try: 
     # program's main code here 
     print("Parsing pmids.txt...") 
     with open('result.html', 'w') as sum_file: 
      sum_file.write('<!--\n') 
     with open('pmids.txt','r') as pmid_file: 
     with open('result.html','a') as sum_file: 
     for pmid in pmid_file: 
      sum_file.write(pmid) 
     sum_file.write('\n-->\n') 
     with open('pmids.txt','r') as pmid_file: 
      h3 = False 
      h4 = False 
      table_mode = False 
      accordion_mode = False 
      with open('result.html', 'a') as sum_file: 
       for pmid in pmid_file: 
        if pmid[:4] == "####": 
         if h3 and not accordion_mode: 
          start_accordion(sum_file) 
          accordion_mode = True 
         sum_file.write('\t\t\t\t\t\t\t\t\t<h4><a href="#">%s</a></h4>\n' % pmid[4:].strip()) 
         h4 = True 
        elif pmid[:3] == "###": 
         if h4: 
          if table_mode: 
           end_table(sum_file) 
           table_mode = False 
          end_accordion(sum_file) 
          h4 = False 
          accordion_mode = False 
         elif h3: 
          end_table(sum_file) 
          table_mode = False 
         sum_file.write('\t\t\t\t\t\t\t\t<h3><a href="#">%s</a></h3>\n' % pmid[3:].strip()) 
         h3 = True       
        elif pmid.strip(): 
         if (h3 or h4) and not table_mode: 
          start_table(sum_file) 
          table_mode = True 
         if pmid[:4] == "http": 
          if pmid[:18] == "http://dx.doi.org/": 
           sum_file.write(PubMedObject(search_term=pmid[18:]).render()) 
          else: 
           print("url=%s" % pmid) 
           p = PubMedObject(url=pmid).render() 
           sum_file.write(p) 
           print(p) 
         elif pmid.isdigit(): 
          sum_file.write(PubMedObject(pmid).render()) 
         else: 
          sum_file.write(PubMedObject(search_term=pmid).render()) 
       if h3: 
        if h4: 
         end_table(sum_file) 
         end_accordion(sum_file) 
        else: 
         end_table(sum_file) 
      pmid_file.close() 
     print("Done!") 

    except BaseException as e: 
     print traceback.format_exc() 
     print "Error: %s %s" % (sys.exc_info()[0], e.args) 
     return 1 
    except: 
     # error handling code here 
     print "Error: %s" % sys.exc_info()[0] 
     return 1 # exit on error 
    else: 
     raw_input("Press enter to exit.") 
     return 0 # exit errorlessly 

if __name__ == '__main__': 
    sys.exit(main(sys.argv)) 

それが今ではダウンロードした情報に基づいてHTMLファイルを返します。テンプレートファイルは次のとおりです。

実行すると、DOIまたはPubmed IDが尋ねられます。あなたが提供していない場合は、pmids.txtと読むでしょう。

+0

はBobortが、私はそれだけで抽象的な情報を取得するように、このコードを微調整するつもりです、ありがとうございました。また、私はpubmed idを構造タイトルと引用タイトルにマップする別のスクリプトとこれを統合します。 –

+0

なぜ私は票を落としましたか?答えを投票して退会するのはどうして役に立たないのですか? – Bobort

+0

こんにちはボボート、私は他の誰かが答えを投票したと思う。私はあなたのためにこれを修正します。 –

1

PubMedの記事の形式は次のとおりです。http://www.ncbi.nlm.nih.gov/pubmed/?Id

あなたがIDを知っているなら、あなたは上記を取得することができますし、記事にアクセスする必要があります。

<div class="abstr"><h3>Abstract</h3><div class=""><p>α-latrotoxin and snake presynaptic phospholipases A2 neurotoxins target the presynaptic membrane of axon terminals of the neuromuscular junction....</p></div></div> 

あなたはそのを抽出するためのツールが必要になります 抽象的には同じ構造内に含まれています。 http://www.crummy.com/software/BeautifulSoup/bs4/doc/

実際にHTMLをフェッチするには、まだツールが必要です。そのためには、phantom.jsやこれまでに普及しているリクエストモジュールを使用します。あなたのワークフローのようなもの希望

pubmed_ids [1,2,3] 
abstracts = [] 

for id in pubmed_ids: 
html_for_id = requests.get('http://www.ncbi.nlm.nih.gov/pubmed/{0}'.format(id)) 
soup = BeautifulSoup(html_for_id) 
abstract = soup.find('selector for abstract') 
abstracts.append(abstract) 
19

と呼ばれるモジュールを使用すると、他のすべてのメタデータとともに非常に簡単にアブストラクトを取得できます。これは、要約を表示します:

from Bio.Entrez import efetch 

def print_abstract(pmid): 
    handle = efetch(db='pubmed', id=pmid, retmode='text', rettype='abstract') 
    print handle.read() 

そしてここでは、XMLを取得し、単に抽象を返す関数です:

from Bio.Entrez import efetch, read 

def fetch_abstract(pmid): 
    handle = efetch(db='pubmed', id=pmid, retmode='xml') 
    xml_data = read(handle)[0] 
    try: 
     article = xml_data['MedlineCitation']['Article'] 
     abstract = article['Abstract']['AbstractText'][0] 
     return abstract 
    except IndexError: 
     return None 

P.S.を私は実際にこのようなことを実際の作業で行う必要があったので、コードをクラスにまとめました - see this gist

+1

これは非常に素晴らしいモジュールのようです。私はそれが存在していることを知らなかった。しかし、私のコードの良い点の1つは、取得されたURLができるだけ一般的なものになるようにDOI値を取得することです。私はそのような機能がEntrezモジュールに存在するかもしれないと仮定していますが、私はそれを深く見ていません。 – Bobort

+0

URLで何を意味するのか分かりません... biopythonはすべてのバックグラウンドでクエリを実行するため、URLを指定する必要はありません。 – Karol

+0

それは大丈夫です。私のアプリケーションは「http://dx.doi.org/」を作成しているので、私はそれをウェブサイトで使うことができます。 PubMedのものに行くのではなく、記事に直接行きたい。私が今すぐ知っている最も一般的な方法は、DOIスキーマを使用することです。 – Bobort

0

「パターン」モジュールは簡単にこれを行うことができますようだ:

from pattern import web 
 
import requests 
 

 
id = 27523945 
 
url = "http://www.ncbi.nlm.nih.gov/pubmed/{0}".format(id) 
 
page = requests.get(url).text.encode('ascii', 'ignore') 
 
dom = web.Element(page) 
 
print(dom.by_tag("abstracttext")[0].content)