Python 清理製表內容的空白分割

在抓取資料時,表格資料會使用製表符號做資料項區隔,方便人眼辨識資訊。

"A       B    C is Great.                     D"

利用 “”.split() 可以使用快速以” “做分隔,產生值為 [“A”, “B”, “C”, “is”, “Great.”, “D”]的串列。不過這樣的結果,並不是期望的[“A”, “B”, “C is Great.”, “D”]串列。

因為是製表符產生的空白,所以項目間的空白長度是浮動的,就沒有辦法利用固定長度洗掉。

這裡面有個資料項是敘述類型,中間帶有” “,需要完整呈現,不能把中間的” “被當成split()的依據。這行資料只是一個樣本,每行資料敘述是不是帶有” “,不一定,” “數量多少也不一定。

但仔細觀察,項目與項目中間的空白會有至少兩個,敘述內的空白只會有一個。

說到「至少兩個空白」的規則,可以使用正則表達式,以「” +”」表示。

搭配””.split(),但因為敘述中會有” “,所以要換個分割符,原則上只要不會出現就好,這裡使用「!@#」。

結合兩者,可以得到以下的程式碼

import re
text = "A       B    C is Great.                     D"
print(re.sub("  +", "!@#", text).split("!@#"))

# => ['A', 'B', 'C is Great.', 'D']

不過,有時候會產生歪斜的字串,可能會出現以下情況

"  A       B    C is Great.                     D"

或是自己鐵了心不想使用re,不想多引用一個套件。

上述的字串經過””.split(” “)以雙空白分割後,串列內會有許多””的,這部分不需要,這時候可以使用filter()將其過濾掉。

filter()這個類別可以設定條件去過濾串列,符合條件的會被過濾掉,留下沒有被過濾掉的。我們可以把””濾掉,””相等None,於是可以寫成以下。

text = "  A       B    C is Great.                     D"
print(text.split("  "))
# => ['', 'A', '', '', ' B', '', 'C is Great.', '', '', '', '', '', '', '', '', '', ' D']

fliter_text = filter(None, text.split("  "))
print(list(fliter_text))
# => ['A', ' B', 'C is Great.', ' D']

雖然項目數目是正確的,但資料項可能會有空白,這是因為單數長度的空白分隔導致,不過也好處理多了。使用””.strip(),可清除頭尾空白。

text = "  A       B    C is Great.                     D"
fliter_text = filter(None, text.split("  "))
print([row.strip() for row in list(fliter_text)])
# => ['A', 'B', 'C is Great.', 'D']