iT邦幫忙

0

Python 文字解析問題

各位大大好
最近小弟嘗試用 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(),因為資安問題
所以打算用基本的字串處理方式,但自己苦苦想不太到解法,所以才上來請教大大們,看有沒有更好的解析方法
感恩感恩

用正則表達式 re 去拆解成你要的資料
然後再map到list
huahualiu iT邦新手 2 級 ‧ 2021-04-28 11:47:33 檢舉
謝謝兩位 @japhenchen @微甜的酸
目前有開始在研究 re,也可以成功抓出我要的元素

不過有個問題
在這樣的情況下:
[(xpath_1_1, xpath_1_2), (xpath_2_1, xpath_2_2), xpath_3...]
使用 re 確實可以各自找出 tuple & 獨立 element 再做拼接

但如果原始資料變成:
[(xpath_1_1, xpath_1_2), xpath_2, (xpath_3_1, xpath_3_2), xpath_4...]
這樣當我先抓 tuple 再抓 獨立 element 進行拼接
原本的順序就會跑掉

在我的狀況中,list 的順序希望是能夠保持一致不變的
請問這樣在實作上有沒有比較好的方向可以進行呢?
謝謝
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

1
bxtkezhan
iT邦新手 5 級 ‧ 2021-04-28 14:14:26
最佳解答
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首個字符
huahualiu iT邦新手 2 級 ‧ 2021-04-28 14:26:40 檢舉

謝謝提供想法,這方法蠻有意思的
/images/emoticon/emoticon41.gif
不過如果要進行匹配與刪除
應該代表我必須先能個別抓出 (A,B)、A、B 元素對吧?
目前比較困難的地方就在於事先無法得知 A、B 是甚麼,而且自己用 re 也有點難抓出 A、B,所以進行匹配這步我可能還沒辦法做

bxtkezhan iT邦新手 5 級 ‧ 2021-04-28 20:21:22 檢舉
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'")
--------------------------------
bxtkezhan iT邦新手 5 級 ‧ 2021-04-28 20:23:43 檢舉

get_single 取出單個tag,get_tuple 取出tuple

我要發表回答

立即登入回答