——前言——
今天跟朋友聊天,聊到了最近几年大专院校的科研发展迅速,想到我妹妹现在就读于江苏的一所医学专科院校,于是我就想查一查她们学校的论文发表情况。简单在pubmed上搜了一下,一共搜出来110多篇带他们学校的论文,不算多,而且其中100多篇都是18年以后才发表的(由此可见近几年医学领域灌水是真厉害...)。粗略看了下,我发现在很多论文中他们学校的人都只是co-author,换句话说论文的第一单位有很多都不是他们学校。于是我就想统计看看他们学校一共发表了多少篇以本校为第一单位的论文,但pubmed的搜索功能里并没有提供第一单位搜索,因此想来想去只能通过爬虫的方式来实现我的需求。好在NCBI提供的API还是蛮齐全的,那就用它的API试试吧!
——过程——
NCBI提供的entrez eutilities包含了多个APIs,这次主要用到的有两个:
1. 按关键词搜索符合条件的论文的PMID:
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=<database>&term=<searching keywords>
2. 根据PMID提取论文信息:
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id=
有了这两个APIs,思路就很很简单:先检索所有符合条件的论文➡提取每篇论文第一个作者的地址信息➡如果第一作者的地址信息符合要求,就记录下来,否则pass。逻辑弄清楚了,代码就简单了:
import requests
import xmltodict
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
'Referer': 'https://eutils.ncbi.nlm.nih.gov/',
'DNT': '1',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'Connection': 'keep-alive',
'Accept-Language': 'zh-CN,zh;q=0.9,en-CN;q=0.8,en;q=0.7',
'Accept-Encoding': 'gzip, deflate',
}
tar_affiliation = '*********' #输入你想要查询的单位的英文名称,如Tsinghua University
def get_uids(tar_affiliation, maxnum):
modified_affiliation = tar_affiliation.replace(' ', '+')
url = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term='+str(modified_affiliation)+'[Affiliation]&retmax=' + str(maxnum)
req = requests.get(url, headers=headers)
req.encoding='utf-8'
html = req.content
root = xmltodict.parse(html)
uidList = root['eSearchResult']['IdList']['Id']
return uidList
def get_content(target_affiliation, MaxQueryNum):
uidlist = get_uids(target_affiliation, MaxQueryNum)
satisfied_uidlist = []
for uid in uidlist:
print('正在检查'+str(uid)+'的单位情况...')
fetchURL = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id='+str(uid)
req = requests.get(fetchURL, headers=headers)
req.encoding = 'utf-8'
html = req.content
root = xmltodict.parse(html)
if(isinstance(root['PubmedArticleSet']['PubmedArticle']['MedlineCitation']['Article']['AuthorList']['Author'][0]['AffiliationInfo'], list) ):
affiliationInfo = root['PubmedArticleSet']['PubmedArticle']['MedlineCitation']['Article']['AuthorList']['Author'][0]['AffiliationInfo'][0]['Affiliation']
else:
affiliationInfo = root['PubmedArticleSet']['PubmedArticle']['MedlineCitation']['Article']['AuthorList']['Author'][0]['AffiliationInfo']['Affiliation']
PMID = root['PubmedArticleSet']['PubmedArticle']['MedlineCitation']['PMID']['#text']
print(str(uid) + '检查完成!')
if tar_affiliation in affiliationInfo:
satisfied_uidlist.append(PMID)
summary = "以"+tar_affiliation+"为第一单位发表的论文一共检索到"+str(len(satisfied_uidlist))+"篇,PMID列表如下所示:"
return summary, satisfied_uidlist
print(get_content(tar_affiliation, <MaxQueryNum>)) #MaxQueryNum是指你想查前多少篇论文,比如我妹妹学校一共就发了110多篇,我就填120。或者某学校近5年发表了1000篇论文,你想看这1000论文的情况,就填1000。
——后记——
以上代码只是作为参考。其实如果搞清楚这个逻辑了,把上述代码改改还是能探讨一些有趣的问题的,比如,获取清华和北大作为第一单位发表CNS的情况(数量,年份等等),跟世界顶尖名校如哈佛,MIT,剑桥等等作比较,看看有没有什么差距。或者你对某个研究人员比较感兴趣,想看看他在某单位以第一作者身份(就不考虑什么共一第二第三这种了)发表的论文情况,把上述代码改改也能实现。