I have a piece of code that downloads acupuncture data from Wikipedia and consolidates it into an acupoint, meridian and extraordinary meridian dictionary stored as .pkl files in the working directory.
import pandas as pd
import wikipedia as wp
import json
from hanziconv import HanziConv as hconv
from copy import deepcopy
from os.path import isfile
import itertools
import re
class Jingluo():
def __init__(self):
self.yinyang = ("太陰", "陽明", "少陰", "太陽", "厥陰", "少陽" )
try:
self.zhengjing, self.xunjing = self.read_meridians()
self.qijing = self.read_extraordinary_meridians()
self.xue = self.read_acupoints()
except:
print("Downloading data from Wikipedia...")
self.get_data_from_wikipedia()
self.zhengjing, self.xunjing = self.read_meridians()
self.qijing = self.read_extraordinary_meridians()
self.xue = self.read_acupoints()
@staticmethod
def get_data_from_wikipedia():
"Scrape data from wikipedia and output three dataframes: \
acupoints, meridians and extraordinary meridians."
html = wp.page("List_of_acupuncture_points").html()
df = pd.read_html(html)
# Set meridian, extra meridian and acupoint
meridians = df[0][['Code', 'Chinese Name', 'English']]
extraordinary_meridians = df[1][['Code','Name','Transliteration']]
extraordinary_meridians.columns = ['ID', 'Name', 'Transliteration']
extraordinary_meridians = extraordinary_meridians.set_index('ID')
acupoints = pd.concat(df[2:16])[['Point', 'Name', 'Transliteration']] # standard :16, all :18
acupoints.columns = ['ID', 'Name', 'Transliteration']
acupoints = acupoints.set_index('ID')
# Data cleaning
## Fix meridian data
meridians = deepcopy(meridians)
meridians['Chinese Name'] = [hconv.toTraditional(item) for item in meridians['Chinese Name']]
meridians.loc[11]['Code'] = 'LR'
## Fix acupoint data
as_list = acupoints.index.tolist()
split_list = [item.split('-') for item in as_list]
tag_list = [tag for tag, sn in split_list]
sn_list = [sn for tag, sn in split_list]
tag_list = ["LR" if tag == "Liv" else tag for tag in tag_list]
tag_list = ["GV" if tag == "Du" else tag for tag in tag_list]
tag_list = ["CV" if tag == "Ren" else tag for tag in tag_list]
tag_list = [item.upper() for item in tag_list]
new_idx_list = [tag + sn for tag, sn in zip(tag_list, sn_list)]
acupoints.index = new_idx_list
# Write to disk
acupoints.to_pickle('acupoints.pkl') # save to pickle file
meridians.to_pickle('meridians.pkl')
extraordinary_meridians.to_pickle('extraordinary_meridians.pkl')
print('Done!')
# 穴位
@staticmethod
def read_acupoints():
if isfile('acupoints.pkl'):
ACUPOINTS = pd.read_pickle('acupoints.pkl')
STRING_LABELS = [name + "(" + index + ")" for name, index in zip(list(ACUPOINTS['Name']), list(ACUPOINTS.index))]
# convert to dictionary
acupoint = {name: {"id": index, "label": name + "(" + index + ")"} for name, index in \
zip(list(ACUPOINTS['Name']), list(ACUPOINTS.index))}
return acupoint
else:
print("Acupoints table not found.")
# 經絡
@staticmethod
def read_meridians():
if isfile('meridians.pkl'):
MERIDIANS = pd.read_pickle('meridians.pkl')
limb_list = [ re.search("([手足])(.+?[陰陽明])(.+)經", item).group(1)\
for item in MERIDIANS['Chinese Name']]
yinyang_list = [ re.search("([手足])(.+?[陰陽明])(.+)經", item).group(2)\
for item in MERIDIANS['Chinese Name']]
organ_list = [ re.search("([手足])(.+?[陰陽明])(.+)經", item).group(3)\
for item in MERIDIANS['Chinese Name']]
zhengjing = { organ:{"id": index, "name": name, "short_name": organ + "經",\
"label": name + "(" + index + ")", "limb": limb, "yinyang": yinyang}\
for name, index, limb, yinyang, organ in \
zip(MERIDIANS['Chinese Name'], MERIDIANS['Code'], limb_list, yinyang_list, organ_list)}
xunjing = (item for item in zhengjing) # generator object; use next(xunjing) to simulate circulation.
return zhengjing, xunjing
else:
print("Meridians table not found.")
#奇經
@staticmethod
def read_extraordinary_meridians():
if isfile('extraordinary_meridians.pkl'):
EXTRAORDINARY_MERIDIANS = pd.read_pickle('extraordinary_meridians.pkl')
em_name_list = [item.split('; ')[1] for item in EXTRAORDINARY_MERIDIANS['Name']]
em_name_list = [re.sub('蹺', '蹻', item) for item in em_name_list]
em_list = [re.sub('脈', '', item) for item in em_name_list]
# hand_meridian_list = [ value['臟腑'] for key, value in .items() if '手' in value['肢'] ]
qijing = {short_hand: {"id": index, "name": name, "label": name + "(" + index + ")"} for short_hand, name, index in \
zip(em_list, em_name_list, list(EXTRAORDINARY_MERIDIANS.index))}
return qijing
else:
print("Extraordinary Meridians table not found.")
You can view the structure of the dataset by running the above initiation code and calling:
x= Jingluo()
x.zhengjing # meridians
x.qijing # extraordinary meridians
x.xue # acupoint data
This is working fine, but I wonder if there a more efficient and effective way of acquiring and storing the above data?
I would like the dataset to be easily extensible. For example, I might want to tag images to show the position of each acupoint in the xue
(i.e. acupoint) dictionary.
It seems to me an SQLite relational database might be more useful for this situation.