Python:利用Entrez庫篩選下載PubMed文獻摘要
一個不是學生物的孩子來搞生物,當真是變成了一塊廢鐵啊,但也是讓我體會到了一把生物資訊的力量。
廢話不多說,開整!
任務:快速高效從PubMed上下載滿足條件的文獻PMID、標題(TI)、摘要(AB)。
PubMed官網 https://pubmed.ncbi.nlm.nih.gov
此處有幾種選擇可以達到目的:
(1)官網上匹配篩選條件(注:匹配快速,但是下載下來的數量受到限制,每次只能下載10000條資料,甚至更少。)
可以看到,我需要的資料是有三十多萬條,但是每次只能下載10000條,那我豈不是要手動n次。。很明顯,在大批量下載文獻的情況下,官網不是很友好。
(2)R語言有個R包,叫做easyPubMed,這裡我也給大家貼上學習指南(https://cran.r-project.org/web/packages/easyPubMed/vignettes/getting_started_with_easyPubMed.html)
由於我不喜歡用R寫程式碼,所以我寫一半還是換了Python,熟練R的小夥伴可以自行根據指南走通需求。
(3)重量級庫來了,Python自帶的Bio包中的Entrez檢索庫,簡直就是我的救星,以下是我的程式碼:
注:Entrez在Bio包中,Bio的安裝請移步 https://www.cnblogs.com/xiaolan-Lin/p/14023147.html
1 import numpy as np 2 from Bio import Medline, Entrez # 一般是通過BioPython的Bio.Entrez模組訪問Entrez 3 from collections import Counter 4 5 Entrez.email = "(此處寫你自己在官網註冊的郵箱賬號)" # 應用自己的賬號訪問NCBI資料庫 6 7 # 此處需將伺服器協議指定為1.0,否則會出現報錯。http.client.IncompleteRead: IncompleteRead(0 bytes read) 8 # 伺服器http協議1.0,而python的是1.1,解決辦法就是指定客戶端http協議版本 9 import http.client 10 http.client.HTTPConnection._http_vsn = 10 11 http.client.HTTPConnection._http_vsn_str = 'HTTP/1.0' 12 13 """ 14 Entrez 是一個檢索系統,可以用其訪問NCBI資料庫,比如說PubMed,GenBank,GEO等。 15 獲得有關 global PBDE 的所有文獻的PubMed IDs 16 """ 17 # handle_0 = Entrez.esearch(db="pubmed", term="drug therapy[Subheading] AND adverse effects[Subheading] AND humans[MeSH Terms]", retmax=306431) 18 handle_0 = Entrez.esearch(db="pubmed", term="drug therapy[MeSH Subheading] AND adverse effects[MeSH Subheading] AND humans[MeSH Terms] AND (2000/01/01[Date - Publication] : 2021/12/31[Date - Publication])", 19 ptyp="Review", usehistory="y", retmax=306431) 20 record = Entrez.read(handle_0) # 獲取檢索條件的所有文獻 21 idlist = record["IdList"] # 提取出文獻id 22 print ("Total: ", record["Count"]) 23 No_Papers = len(idlist) # 共306431篇文獻 2000-01-01:2021-12-31 24 webenv = record['WebEnv'] 25 query_key = record['QueryKey'] 26 27 total = No_Papers 28 step = 1300 29 print("Result items:", total) 30 with open("./Data_PubMed/PBDE1.txt", 'w') as f: 31 for start in range(0, total, step): 32 print("Download record %i to %i" % (start + 1, int(start + step))) 33 handle_1 = Entrez.efetch(db="pubmed", retstart=start, rettype="medline", retmode="text", 34 retmax=step, webenv=webenv, query_key=query_key) # 獲取上述所有文獻的PubMed IDs 35 records = Medline.parse(handle_1) 36 records = list(records) # 將迭代器轉換至列表(list) 37 for index in np.arange(len(records)): 38 id = records[index].get("PMID", "?") 39 title = records[index].get("TI", "?") 40 title = title.replace('[', '').replace('].', '') # 若提取的標題出現[].符號,則去除 41 abstract = records[index].get("AB", "?") 42 f.write(id) 43 f.write("\n") 44 f.write(title) 45 f.write("\n") 46 f.write(abstract) 47 f.write("\n")
話不多說,結果跑出來了我真的很快樂~
最後的結果是存放在txt檔案中,大夥兒根據自己的需求改變程式碼所需欄位啊。
現在我來解釋一下,我貼上的這串程式碼的實現原理,首先是通過Entrez檢索到符合我篩選條件的文獻,裡邊的限制條件包括了幾個詞彙匹配以及時間限制,時間我限制在了2000年1月1日到2021年的12月31日(這裡的時間我選用的是Date - Publication,時間選取Date - Completion、Date - Modification還是Date - Publication其實還是有爭議的,大家自行考慮選取)。
Entrez.esearch的作用就是用來檢索的,裡邊的引數db指向你要檢索的資料庫,程式碼中的註釋也寫了,Entrez作為一個介面檢索,除了能夠檢索PubMed中的文獻,也能去到別的資料庫檢索文獻;term是寫你的篩選語句,注意你寫的檢索語句不能帶有引號,單引號也不行,否則會檢索不到,如果不知道檢索語句怎麼寫,或者是不知道欄位是否被定義,可以在官網的檢索那裡https://pubmed.ncbi.nlm.nih.gov/advanced/選擇欄位輸入內容自動生成query,但是生成的語句是不太智慧的,會有很多括號是你不需要的,自己寫程式碼的時候要適當去掉;ptyp我這裡用的是Review,usehistory是y,意思是後邊我的檢索要記住這個語句,根據歷史查詢來檢索;retmax如果不進行設定的話,預設給你的最大資料量好像是隻有1000,我要的檢索內容是超過這個值的,因此我需要自定義檢索的數量。
Entrez.read是對Entrez.esearch檢索到的內容進行讀取,裡邊包含了9種元素,我們主要是想從中得到文獻的id號,只有拿到了文獻的id號,我們後面進行摘要的提取才能準確定位。
最後是迴圈當中步長的設定,這裡就要根據自己的需求來定義了,包括內容的提取,因為我只需要PMID、標題(TI)、摘要(AB),所以我就沒有載入別的內容進來,這裡也有一點要注意,標題下載下來是大部分帶有[ ].的,方便操作我直接就在下載的時候給去除了,這也是上面replace程式碼的由來。
附上我參考的連結,如果我這篇文章解決不了你的問題,那麼希望下面的渠道能夠幫助到你
https://zhuanlan.zhihu.com/p/54611852
https://zhuanlan.zhihu.com/p/262957260