簡體   English   中英

從二進制文件中提取文本(在Windows 7上使用Python 2.7)

[英]Extract Text from a Binary File (using Python 2.7 on Windows 7)

我有一個大約5MB的二進制文件..其中有很多散布的文本..和控制字符..

這實際上等效於SITATEX Application(來自SITA)的Outlook .pst文件。

該文件包含所有與外界發送和接收的文本消息...(但文本必須通過二進制控制字符提取)..所有文本消息均清晰可見...以^ M字符結尾的行...等

例如:假設^ @ ^ X是控制字符... \\ xaa,十六進制為aa,等等。在我所需的文本提取周圍加載了它們。

^@^@^@^@^@^@^@^@^@^@^@BLLBBCC^X^X^X^X^X^X^X^X^X
^X^X^X
MVT^M
EA1123 TEXT TEXT TEXT^M
END^M
\xaa^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
 ^@^@^@^@^@^@^@^@^@^@^@TTBBTT^X^X^X^X^X^X^X^X^X
   ^X^X^X blah blah blah... of control characters.. and then the message comes..
   MVT MESSAGE 2
   ED1123
   etc.

等等..對於一些消息。

使用Perl ..很容易做到:

while (<>) {
  use regular expression to split messages
  m/   /


}

如何在python中輕松做到這一點。

  1. 如何讀取文件? 二進制和文本穿插
  2. 消除不必要的控制字符
  3. 解析兩個\\ xaa有用文本信息\\ xaa之間的消息(十六進制'aa')
  4. 打印出所需的東西
  5. 循環瀏覽所有行..和更多文件。

在文本文件示例中……我感興趣的是……BLLBBCC……以及MVT和EA1123等。

請協助...如果在python中將非常困難..我將不得不仔細考慮perl本身的邏輯..因為它(perl)至少在循環部分不會給我帶來很多錯誤二進制和文本的東西..和正則表達式。

謝謝。

閱讀您的答案/評論后更新02 Jan

經過S.Lott的評論和其他...之后,我在這里..,並且可以正常工作80%。

import fileinput
import sys
import re

strfile = r'C:\Users\' \
          r'\Learn\python\mvt\sitatex_test.msgs'

f = open(strfile, 'rb')

contents = f.read() # read whole file in contents

#extract the string between two \xaaU.. multiline pattern match
#with look ahead assertion
#and this is stored in a list with all msgs
msgs = re.findall(r'\xaaU.*?(?=\xaaU)', contents, re.I|re.DOTALL|re.M)

for msg in msgs:
    #loop through msgs.. to find the first msg then next and so on.
    print "## NEW MESSAGE STARTS HERE ##"

    #for each msg split the lines.. to read line by line
    # stored as list in msglines
    msglines = msg.splitlines()
    line = 0
#then process each msgline with a message
for msgline in msglines:
    line += 1
    #msgline = re.sub(r'[\x00]+', r' ', msgline)
    mystr = msgline
    print mystr
    textstrings = re.findall(r'[\x00\x20-\x7E]+', msgline)

到目前為止還不錯..我還沒有完全完成..因為我需要逐行和逐字地解析文本..(例如)提取原始地址和標題,主題行,消息正文。通過控制字符來解析消息。

現在,我被困在...如何逐行打印轉換為\\x00\\x02..等(使用\\xHH格式)的控制字符..卻不打擾普通可讀文本。

例如..說我有這個:假設^@^X是一些控制字符line1 = '^@UG^@^@^@^@^@^@^@^@^@^@BLLBBCC^X^X^X^X^X^X^X^X^X' (在第一行)。

當我在IDLE ..上打印該行時.. print line1 ..它只說前2或3個字符..並忽略其余字符,因為控制字符被阻塞。

但是,當我用以下命令print re.findall(r'.*', line1)時: print re.findall(r'.*', line1)

['\xaaUG\x02\x05\x00\x04\x00\x00\x00\x05\x00\x00\x00....
x00\x00\x00..BLLBBCC\x00\x00N\x00N\\x00
 002 010 180000 DEC 11', '']

它將所有控制字符轉換為\\ xHH格式..並完整保留ascii文本..(正如我想要的那樣)..列表中有兩個項目..最后帶有“。”,打印效果很好。

  1. 最后對空字符串的解釋是什么?
  2. 如何避免它...我只是希望將行很好地轉換為字符串(而不是列表)。 例如,一行二進制/文本將被轉換為帶有\\ xHH代碼的字符串..單獨保留ASCII TEXT。

使用re.findall(r'.*', line1)是唯一簡單的解決方案..進行此轉換..或是否有任何其他直接的方法..將'\\x00string'轉換為\\ xHH和TEXT(其中它是可打印的字符或空白)。

還..任何其他有用的意見,以使線條很好。

謝謝。

更新2Jan2011-第2部分

我發現re.findall(r'.+', line1)剝離到

['\xaaUG\x02\x05\x00\x04\x00\x00\x00\x05\x00\x00\x00....
    x00\x00\x00..BLLBBCC\x00\x00N\x00N\\x00
     002 010 180000 DEC 11']

列表中沒有多余的空白''項目。 這一發現經過無數次反復試驗。

我仍然需要幫助才能完全消除該列表,但只返回一個字符串。 像這樣:

'\xaaUG\x02\x05\x00\x04..BLLBBCC..002 010 180000 DEC 11'

在05Jan上添加了信息:

@約翰·馬欽

1)\\ xaaU是消息之間的分隔符..在示例中..我可能在示例中已經忽略了。 請參閱以下有關以\\ xaaU結尾(但未列出)的實際消息。 從repr( r'\\xaaU.*?(?=\\xaaU)'之間的msg)獲得以下文本

我正在嘗試理解二進制格式..這是一條典型的消息,它是從第一個'JJJOWXH'發送出去的,它是發送方地址..后面跟有7個字母數字的任何內容都是接收方地址..基於發送方地址..我知道這是'SND'還是'RCV'..因為來源是'JJJOWXH'...這個味精是'SND',就像我們是'JJJOWXH'。

該消息已發送至:JJJKLXH .... JJJKRXH ....等。

所有.. \\ x00000000完成后.. sita頭文件和主題開始在這種特殊情況下... "\\x00QN\\x00HX\\x00180001 \\x00"這是頭文件。我只對之間的所有內容感興趣\\ x00。

並在下一個\\ .00或任何其他控制字符之后出現主體。在這種情況下,它是:

COR \\ r \\ nMVT \\ r \\ nHX9136 / 17.BLNZ.JJJ \\ r \\ nAD2309 / 2314 EA0128 BBB \\ r \\ nDLRA / CI / 0032/0022 \\ r \\ nSI EET 02:14 HRS \\ r \\ n RA / 0032 DUE延遲ARVL ACFT \\ r \\ n CI / 0022卸載懸空托盤,由於包裝不足導致\\ r \\ n空間問題

一旦可讀文本結束...出現在第一個\\ xaaU之前的第一個控制字符將被忽略...在上述情況下,“空格問題”是最后一個..然后控制字符開始...因此可以忽略...有時直到下一個\\ xaaU都沒有控制字符。

這是一條完整的消息。

“ \\ xaaU \\ x1c \\ x04 \\ x02 \\ x00 \\ x05 \\ x06 \\ x1f \\ x00 \\ x19 \\ x00 \\ x00 \\ x00 \\ xc4 \\ x9d \\ xedN \\ x1a \\ x00?\\ x02 \\ x02 \\ x00 \\ x00B \\ x02 \\ x02 \\ x00E \\ x02 \\ x07 \\ x00 \\ xff \\ xff \\ x00 \\ x00 \\ xff \\ xff \\ x00 \\ x00 \\ xff \\ xff \\ x00 \\ x00M \\ x02 \\ xec \\ x00 \\ xff \\ xff \\ x00 \\ x00 \\ x00 \\ x00?\\ x02M \\ x02 \\ xec \\ x00 \\ xff \\ xff \\ x00 \\ x00 \\ xff \\ xff \\ x00 \\ x00 \\ xff \\ xff \\ x00 \\ x00 \\ xff \\ xff \\ x00 \\ x00 \\ xff \\ xff \\ x00 \\ x00:\\ x03 \\ x10 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x7f \\ x00JJJOWXH \\ x00 \\ x05w \\ x01x \\ x01 \\ x00 \\ x01JJJKLXH \\ x00 \\ x00 \\ x7f \\ x01 \\ x80 \\ x01 \\ x00 \\ x01 \\ x01JJKRXH \\ x00F \\ x87 \\ x88 \\ x01 \\ x00 \\ x01JJJFFXH \\ x00 \\ xff \\ x8f \\ x01 \\ x90 \\ x01 \\ x00 \\ x01JJJFCXH \\ x00 \\ xff \\ x97 \\ x01 \\ x98 \\ x01 \\ x00 \\ x01JJJFAXH \\ x00 \\ x00 \\ x9f \\ x01 \\ xa0 \\ x01 \\ x00 \\ x01JJJKPXH \\ x00 \\ x00 \\ xa7 \\ x01 \\ xa8 \\ x01 \\ x00 \\ x01 \\ x01HAKUOHU \\ x00 \\ x00 \\ xaf \\ x01 \\ xb0 \\ x01 \\ x00 \\ x01BBBHRXH \\ x00 \\ x00 \\ xb7 \\ x01 \\ xb8 \\ x01 \\ x00 \\ x01BBBFFHX \\ x00 \\ x00 \\ xbf \\ x01 \\ xc0 \\ x01 \\ x00 \\ x01 \\ x01BBBOMHX \\ x00 \\ x00 \\ xc7 \\ x01 \\ x01 \\ x01 \\ x00 \\ x01BBBFMXH \\ x00 \\ x00 \\ xcf \\ x01 \\ xd0 \\ x01 \\ x00 \\ x01 \\ x01JJJHBER \\ x00 \\ x00 \\ xd7 \\ x01 \\ xd8 \\ x01 \\ x00 \\ x01BBBFRUO \\ x00 \\ x00 \\ xdf \\ x01 \\ xe0 \\ x01 \\ x00 \\ x01BBBKKHX \\ x00 \\ x00 \\ xe7 \\ x01 \\ xe8 \\ x01 \\ x00 \\ x01JJJLOTG \\ x00 \\ x01 \\ xef \\ x01 \\ xf0 \\ x01 \\ x00 \\ x01JJJLCTG \\ x00 \\ x00 \\ x00 \\ xf7 \\ x01 \\ xf8 \\ x01 \\ x01 \\ x00 \\ x01HDQOMTG \\ x005 \\ xff \\ x01 \\ x00 \\ x02 \\ x00 \\ x01CHACSHX \\ x00K \\ x07 \\ x02 \\ x08 \\ x02 \\ x00 \\ x01JJJKZXH \\ x00F \\ x0f \\ x02 \\ x10 \\ x10 \\ x02 \\ x00 \\ x01BBBOMUO \\ x00 \\ x17 \\ x10 \\ x18 \\ x02 \\ x00 \\ x01BBBORXH \\ x00 \\ x1f \\ x02 \\ x02 \\ x00 \\ x01BBBOPXH \\ x00W'\\ x02(\\ x02 \\ x00 \\ x01CHACSHX \\ x00 / \\ x020 \\ x02 \\ x00 \\ x00 \\ x01JJJDBXH \\ x0007 \\ x028 \\ x02 x00010000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00 \\ x00000000 \\ x00QN \\ x00HX \\ x00180001 \\ x00COR \\ r \\ nMVT \\ r \\ nHX9136 / 17.BLNZ.JJJ \\ r \\ nAD2309 / 2314 EA0128 BBB \\ r \\ nDLRA / CI / 0032/0022 \\ r \\ nSI EET 02:14 HRS \\ r \\ n RA / 0032由於遲到的ARVL ACFT \\ r \\ n CI / 0022卸載了懸空的托盤由於不適當的包裝領導到\\ r \\ n空間問題\\ x00D- \\ xedN \\ x00 \\ x04 \\ x1a \\ x00t <\\ x93 \\ x01x \\ x00M_ \\ x00”

2)在知道'repr'之后,我不再使用。+了。

3)每條消息都是多行的..我需要保留所有控制字符以使這種專有格式有意義。這就是為什么我需要repr才能近距離查看它。

希望這能解釋...這只是文件中每1000條中的1條消息...有些是'SND',有些是'RCV'...對於'RCV'不會有'000000'。偶爾會有一些例外情況...但是通常沒關系。

任何人的任何進一步建議..我仍在處理文件..完整地檢索文本...具有發送者和接收者的地址。

謝謝。

問:如何讀取文件? 二進制和文本穿插

答:不用理會,只需將其閱讀為普通文本即可,並且可以保持二進制/文本二分法(否則您將無法輕松對其進行正則表達式處理)

fh = open('/path/to/my/file.ext', 'r')
fh.read()

萬一您出於某種原因以后想要讀取二進制文件,只需將ab添加到open的第二個輸入中:

fh = open('/path/to/my/file.ext', 'rb')

問:消除不必要的控制字符

答:使用python re模塊。 您的下一個問題有點問如何

問:解析兩個\\ xaa有用的文本信息\\ xaa之間的消息(十六進制'aa')

答:re模塊具有findall函數,該函數按您(通常)的預期工作。

import re

mytext = '\xaaUseful text that I want to keep\xaa^X^X^X\xaaOther text i like\xaa'
usefultext = re.findall('\xaa([a-zA-Z^!-~0-9 ]+)\xaa', mytext)

問:打印出所需的東西

* A:有打印功能...

print usefultext

問:循環瀏覽所有行..和更多文件。

fh = open('/some/file.ext','r')

for lines in fh.readlines():
    #do stuff

我讓您找出os模塊,找出存在的文件/如何遍歷它們。

Python也支持正則表達式。 我不會說Perl,所以我不知道您的Perl代碼到底是做什么的,但是這個Python程序可能會幫助您:

import re
with open('yourfile.pst') as f:
    contents = f.read()
textstrings = re.findall(r'[\x20-\x7E]+', contents)

這將為您提供文件中一個或多個ASCII可打印字符的所有字符串的列表。 那可能並不是您想要的,但是您可以從那里對其進行調整。

請注意,如果您使用的是Python 3,則必須擔心二進制數據和文本數據之間的區別,它將變得更加復雜。 我假設您使用的是Python 2。

你說:

我仍然需要幫助才能完全消除該列表,但只返回一個字符串。 像這樣

換句話說,您具有foo = [some_string]並且您正在執行print foo ,它的一面確實是repr(some_string)但將其括在不需要的方括號中。 因此,只需print repr(foo[0])

似乎有些原因無法解釋:

  1. 您說有用的文本用\\xaaU括起來,但是在示例文件中,開始位置附近只有\\xaa (缺少U ),而不是該分隔符的2次出現。

  2. 你說

    我發現re.findall(r'。+',line1)條帶到...

    實際上,這是剝離\\n (而不是\\r !!)-我認為嘗試恢復電子郵件時應該保留換行符。

     >>> re.findall(r'.+', 'abc\\r\\ndef\\r\\n\\r\\n') ['abc\\r', 'def\\r', '\\r'] 

    您使用\\r字符做了什么? 您是否測試了多行消息? 您是否測試了多消息文件?

  3. 剩下的就是猜測誰或什么打算消耗您的輸出。 你寫

    我需要逐行和逐詞解析文本

    但是您似乎過於擔心使用\\xab而不是亂碼來“清晰地”打印消息。

  4. 看起來您最新代碼中的最后6行左右( for msgline in msglines:等等)應該縮進一個級別。

是否可以澄清以上所有內容?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM