NCBI(pubmed)里医学主题词(MeSH)完整词库获取
转载提示:原创文章,转载前请联系我!!
文章目录
前言
本文主要介绍MeSH词库的获取方法,有两种方式:1.官网的下载页面,2.对网页进行爬取。本文主要介绍第二种方法。MeSH词库官网:https://www.ncbi.nlm.nih.gov/mesh
一、MeSH词库是什么?
医学主题词(MeSH)是一种用于生物医学信息的索引和分类的层次结构术语。它用于为PubMed和其他NLM数据库建立索引。
二、获取MeSH词库的方式
根据项目需要选择适合项目的获取方式!!!
1.从官网的下载页面里下载
下载页面:https://www.nlm.nih.gov/databases/download/mesh.html
2.使用python和requests对网页进行爬取
在官网下载页面下载的数据清洗也比较费时费力,而且此网站没有反爬,能轻松获取到我们想要的数据,所以爬取也是一种较好的方式。
三、使用python和requests对网页进行爬取
1.项目需求
- 提供一个完整的MeSH词库,供项目使用。需要上下级关系,能够根据需要搜索的词找到它本身的同义词和它的所有下级节点以及它的所有下级节点的同义词。
2.网站特点
-
以下图为例,搜索Dental Care,网址:https://www.ncbi.nlm.nih.gov/mesh/68003729
-
上图可以看出:词在词库的位置有两个,以逗号分隔,并且下面树状结构也是两个。只要我们把每一个词和它在词库里的位置都获取下来,就能得到一个完整得词库。使用时只需找出词在词库的位置,根据词在词库的位置就能找到它所有的下级词。
-
例:上图搜索的词是Dental Care,词在词库的位置是E06.170和N02.421.240.190,它的下级词的位置必定包含上面两个,格式是E06.170.xxx 或N02.421.240.190.xxx,所以找出所有包含上面两个位置的词就是Dental Care的下级词。例如用鼠标点击下级词:Dental Care for Aged,它在词库里的位置是E06.170.100和N02.421.240.190.210,可见有了Dental Care在词库的位置就能查出它所有的下级词。
3.爬取目标
目标:获取网页上每一个词以及它的Entry Terms和Tree Number(s)。
实际爬虫的时候:为了将整个词库完整得获取下来,就需要将搜索词的下级词的href网址也都获取下来,然后遍历。
下图示例:若看不清可保存图片放大!!!!
官网:https://www.ncbi.nlm.nih.gov
例:下级词的href="/mesh/68016321",它的url就是官网+href。
url:https://www.ncbi.nlm.nih.gov/mesh/68016321
4.存储格式
- 我是用txt存储的,也可选择其他格式!!
- 卍分割1.搜索的词与2.词在词库里的位置,※分割1.搜索的词与3.词的同义词
5.项目文件
6.具体代码
# -*- coding: utf-8 -*-
import requests
import time
from lxml import etree
import pandas as pd
# 作者:csdn.美味大香蕉
# 日期:2020-11-10
# 卍分割1.搜索的词与2.词在词库里的位置,※分割1.搜索的词与3.词的同义词
#写入txt
def writeTxt(text):
file = open('./data.txt', 'a', encoding='utf-8')
file.write(text + "\n")
file.close()
#爬取网页
def Request(url):
response = requests.get(url,timeout=10)
time.sleep(2)
# print(response)
response.encoding = 'utf-8'
textData = response.text
resHtml = etree.HTML(textData.encode('utf-8'))
return resHtml
#主程序
def crawl():
#官网
baseUrl="https://www.ncbi.nlm.nih.gov"
#起始词All MeSH Categories
queueHref=["/mesh/1000048"]
endHref=[]
#统计写入txt的数据量
num=0
#标记错误链接的重试次数
tag=0
#开始时间
startTime=time.time()
while queueHref !=[]:
try:
headHref=queueHref[0]
print(headHref)
#拼接url
url = baseUrl + headHref
#获取网页
html=Request(url)
#从网页上获取href
xpath = '//*[@id="maincontent"]/div/div[5]/div//@href'
hrefData = html.xpath(xpath)
if len(hrefData)>0:
for h in hrefData:
if h not in endHref and h not in queueHref and h[:6] =="/mesh/":
queueHref.append(h)
# 从网页上获取 词
nameXpath = '//*[@id="maincontent"]/div/div[5]/div/h1/text()'
nameData=html.xpath(nameXpath)
# 从网页上获取 entryTerms
entryTermsXpath = '//*[@id="maincontent"]/div/div[5]/div/ul[1]/*/text()'
entryTermsData = html.xpath(entryTermsXpath)
entryTerms=""
if len(entryTermsData)>1:
entryTermsData3=[]
for e in range(len(entryTermsData)):
entryTermsXpath2 = '//*[@id="maincontent"]/div/div[5]/div/ul[1]/li['+str(e+1)+']//text()'
entryTermsData2 = html.xpath(entryTermsXpath2)
if len(entryTermsData2)>0:
entryTermsData3.append("".join(entryTermsData2))
entryTerms="※".join(entryTermsData3)
elif len(entryTermsData)==1:
if entryTermsData[0] !="All MeSH Categories":
entryTerms = entryTermsData[0]
# 从网页上获取 Tree Number(s)
idXpath = '//*[@id="maincontent"]/div/div[5]/div/p/text()'
idData=html.xpath(idXpath)
if len(idData)>0:
for i2 in idData:
if "Tree Number(s): " in i2:
ids=i2.replace("Tree Number(s): ","")
ids=ids.split(", ")
#将数据写入txt
for id in ids:
writeTxt(id + "卍" + nameData[0]+"※"+entryTerms)
num+=1
print("已写入第"+str(num)+"个数据。")
#更新queueHref和endHref
queueHref.remove(headHref)
endHref.append(headHref)
tag = 0
except:
#若重试次数等于10次,就将错误的Href保存至errorLog.txt
if tag==10:
queueHref.remove(headHref)
endHref.append(headHref)
file = open('./errorLog.txt', 'a', encoding='utf-8')
file.write(headHref + "\n")
file.close()
tag = 0
print("*" * 30)
print("数据错误,已保存至txt!!!!!!")
print("*" * 30)
tag+=1
#保存queueHref和endHref
pd.to_pickle(queueHref, "./queueHref.pkl")
pd.to_pickle(endHref, "./endHref.pkl")
#读取queueHref和endHref
endHref = pd.read_pickle("./endHref.pkl")
queueHref = pd.read_pickle("./queueHref.pkl")
#发生错误的时间
zTime=time.time()
print("*" * 30)
print("已用时:"+str(zTime-startTime)+"秒!!")
print("发生错误,程序10秒后自动开始运行,!!!!!!")
print("*" * 30)
time.sleep(10)
#程序运行完的时间
endTime=time.time()
print("※" * 30)
print("总用时:"+str(endTime-startTime)+"秒!!")
print("爬取完成!!")
print("※" * 30)
if __name__=="__main__":
crawl()
7.项目成果
总结
上面项目和代码只是本人演示交流所用,请各位帅哥美女根据实际项目需要再做修改。