各位大大好
最近小弟嘗試用 Python 寫一個文字(xpath)解析的工具
主要是讓 user 可以自行輸入需要的 xpath 組(輸入方式是預先定義的格式)
我的 function 會進行解析,將格式轉成程式可讀取的資料結構
Input 如下:(這會從 Excel 上面擷取)(string 內可以是 tuple 或單一元素)
sig = "(xpath_1_1, xpath_1_2), (xpath_2_1, xpath_2_2), xpath_3..."
預期 Output 進行如下轉換:(轉換成內含tuple 或單一元素的 List 資料格式)
[(xpath_1_1, xpath_1_2), (xpath_2_1, xpath_2_2), xpath_3...]
目前一組測資如下:
sig = "(//div[@style='font-family:Arial;float: left;width:930px;font-size:12px;' and ./span[contains(text(),'005930')]], //table[@id='gv_flow_krKS0 1']),(//div[@style='font-family:Arial;float: left;width:930px;font-size:12px;' and ./span[contains(text(),'000660')]], //table[@id='gv_flow_krKS0 2'])"
想請問有沒有甚麼比較好的轉換策略呢?
目前不考慮使用 eval(),因為資安問題
所以打算用基本的字串處理方式,但自己苦苦想不太到解法,所以才上來請教大大們,看有沒有更好的解析方法
感恩感恩
inputs = '(A, B), A, A, (A, B), (A, B)'
While len(inputs):
if 匹配(A, B)成功且匹配內容從下標0開始:
記錄匹配內容,修改inputs「移除匹配的內容」
continue
if 匹配A成功且匹配內容從下標0開始:
記錄匹配內容,修改inputs「移除匹配的內容」
continue
inputs = inputs[1:] # 去除inputs首個字符
謝謝提供想法,這方法蠻有意思的
不過如果要進行匹配與刪除
應該代表我必須先能個別抓出 (A,B)、A、B 元素對吧?
目前比較困難的地方就在於事先無法得知 A、B 是甚麼,而且自己用 re 也有點難抓出 A、B,所以進行匹配這步我可能還沒辦法做
inputs = '''
(
//div[@style='font-family:Arial;float: left;width:930px;font-size:12px;' and ./span[contains(text(),'005930')]],
//table[@id='gv_flow_krKS0 1']
),
(
//div[@style='font-family:Arial;float: left;width:930px;font-size:12px;' and ./span[contains(text(),'000660')]],
//table[@id='gv_flow_krKS0 2']
)
'''
def get_attrs(s:str):
s = s.lstrip()
if not s.startswith('['): return
flag = 0
attrs = ''
for i, c in enumerate(s):
if c == '[':
flag += 1
elif c == ']':
flag -= 1
if flag == 0:
return attrs, s[i + 1:]
elif flag > 0:
attrs += c
def get_single(s:str):
s = s.lstrip()
if not s.startswith('//'): return
s = s[2:]
tag = ''
for c in s:
if c.isalnum():
tag += c
else:
break
s = s[len(tag):]
ret = get_attrs(s)
if not ret: return
return (tag, ret[0]), ret[1]
def get_tuple(s:str):
def _jump_chars(s:str):
position = 0
while s[position] in ' \n,':
position += 1
return s[position:]
if not s.startswith('('): return
s = _jump_chars(s[1:])
item1 = get_single(s)
if not item1: return
s = _jump_chars(item1[1])
item2 = get_single(s)
if not item2: return
s = item2[1].lstrip()
if s.startswith(')'):
return (item1[0], item2[0]), s[1:]
logs = []
while len(inputs):
ret = get_tuple(inputs)
if ret:
logs.extend(ret[0])
inputs = ret[1]
continue
ret = get_single(inputs)
if ret:
logs.append(ret[0])
inputs = ret[1]
continue
inputs = inputs[1:]
for line in logs:
print(line)
print('-' * 32)
輸出:
('div', "@style='font-family:Arial;float: left;width:930px;font-size:12px;' and ./spancontains(text(),'005930')")
--------------------------------
('table', "@id='gv_flow_krKS0 1'")
--------------------------------
('div', "@style='font-family:Arial;float: left;width:930px;font-size:12px;' and ./spancontains(text(),'000660')")
--------------------------------
('table', "@id='gv_flow_krKS0 2'")
--------------------------------
get_single 取出單個tag,get_tuple 取出tuple