Python Pyparsing-从混合jascii/ascii文本文件解析jascii文本?
我有一个混合了jascii/shift jis和ascii文本的文本文件。我正在使用Python Pyparsing-从混合jascii/ascii文本文件解析jascii文本?,python,parsing,ascii,pyparsing,shift-jis,Python,Parsing,Ascii,Pyparsing,Shift Jis,我有一个混合了jascii/shift jis和ascii文本的文本文件。我正在使用pyparsing,无法标记这些字符串 下面是一个示例代码: from pyparsing import * subrange = r"[\0x%x40-\0x%x7e\0x%x80-\0x%xFC]" shiftJisChars = u''.join(srange(subrange % (i,i,i,i)) for i in range(0x81,0x9f+1) + range(0xe0,0xfc+1)) j
pyparsing
,无法标记这些字符串
下面是一个示例代码:
from pyparsing import *
subrange = r"[\0x%x40-\0x%x7e\0x%x80-\0x%xFC]"
shiftJisChars = u''.join(srange(subrange % (i,i,i,i)) for i in range(0x81,0x9f+1) + range(0xe0,0xfc+1))
jasciistring = Word(shiftJisChars)
jasciistring.parseString(open('shiftjis.txt').read())
我得到:
Traceback (most recent call last):
File "test.py", line 7, in
jasciistring.parseString(open('shiftjis.txt').read())
File "C:\python\lib\site-packages\pyparsing.py", line 1100, in parseString
raise exc pyparsing.ParseException
回溯(最近一次呼叫最后一次):
文件“test.py”,第7行,在
parseString(open('shiftjis.txt').read())
文件“C:\python\lib\site packages\pyparsing.py”,第1100行,parseString格式
raise exc pyparsing.ParseException
这是文本文件的内容:
"‚s‚ˆ‚‰‚“@‚‰‚“@‚@‚“‚ˆ‚‰‚†‚”[‚Š‚‰‚“@‚“‚”‚’‚‰‚Ž‚‡B"
“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“s”“
(无引号)我首先想到的是,您没有将文件作为二进制文件打开。我建议使用类似于
open('shiftjis.txt',rb')的代码
。您知道该文件包含超出正常ASCII范围的字符,因此通常最好将该文件作为二进制文件打开,然后将其内容解码为Unicode。或许可以使用以下类似方法(假设“shift jis”是正确的编解码器名称):
如果parseString()
需要一个str
对象(与unicode
对象相反),则可以使用UTF-8将最后一行更改为编码text
:
jasciistring.parseString(text.encode('utf-8'))
我唯一的另一个建议是验证jascisistring
是否包含正确的语法;因为您正在使用十六进制范围构造它,我希望您首先将其视为二进制str
,然后将其解码为unicode
对象。您的“文本文件内容”是(由于使用错误的编解码器解码文件而显示垃圾)。我猜测了错误的编解码器,对文本进行了重新编码,使用ShiftJIS进行解码,得到:
# coding: utf8
import codecs
s = u'‚s‚ˆ‚‰‚“@‚‰‚“@‚@‚“‚ˆ‚‰‚†‚”[‚Š‚‰‚“@‚“‚”‚’‚‰‚Ž‚‡B'
s = s.encode('cp1252').decode('shift-jis','replace')
print s
输出
因此,默认的美国Windows编解码器不太合适:^)
很可能您只需使用shift_jis编解码器读取原始文件:
import codecs
f = codecs.open('shiftjis.txt','rb','shift_jis')
data = f.read()
f.close
数据
将是一个包含解码字符的Unicode字符串。当您遇到非ASCII字符/字节的问题时,将其打印到控制台并将其复制到问题中是毫无帮助的。您看到的往往不是您得到的。您应该使用内置的repr()
功能[Python3.x:ascii()
]以尽可能清晰地显示数据
这样做:
python -c "print repr(open('shiftjis.txt', 'rb').read())"
并将结果复制/粘贴到“编辑您的问题”对话框中
在等待启示的同时反向工程您的数据:Windows代码页必须是一个很好的嫌疑犯,最常见的是cp1252
。正如@Mark Tolonen所示,cp1252
几乎适合,只有一个错误。进一步的调查显示,另一个cp125x
编码产生2、3或5个错误。AFAIK只有cp125x
编码会将看起来像逗号的东西(实际上是U+201A一个低9引号)映射到shift jis前导字节\x82
。我得出结论,违规者是cp1252
,错误是由运输途中的损坏造成的
另一种可能是,底层原始编码不是shift jis,而是其超集,即在日文Windows上使用的Microsoft的cp932
。但是有问题的序列'\x82@'
在cp932
中也无效。在任何情况下,如果文件您要处理的数据来自日本Windows计算机,最好使用cp932
而不是shift-jis
从你的问题和你的代码看,你想做什么,以及为什么你想用字节范围而不是仅仅将数据解码为Unicode,这都不明显。我不使用pyparsing
,但似乎很有可能你输入的子范围格式不正确
下面是一个如何使用正则表达式标记输入的示例。请注意,pyparsing语法略有不同(\0xff
而不是Python的“\xff”)
代码:
注1:您不需要循环并加入O(N**2)个字符范围
如果“jascii”只是指“全宽拉丁(大写|小写)字母[A-Z]”(A)您的网络太大(b)您可以轻松地使用UNICODE字符范围而不是字节范围(当然,在解码数据后).不仅代码不可读,而且您还忘记了放置完整的回溯。当您要在帖子中放置代码或回溯时,请突出显示相关文本并转到编辑工具栏…有一个类似于
{}
的按钮。请使用它。
import codecs
f = codecs.open('shiftjis.txt','rb','shift_jis')
data = f.read()
f.close
python -c "print repr(open('shiftjis.txt', 'rb').read())"
import re, unicodedata
input_bytes = '\x82s\x82\x88\x82\x89\x82\x93@\x82\x89\x82\x93@\x82@\x82\x93\x82\x88\x82\x89\x82\x86\x82\x94[\x82\x8a\x82\x89\x82\x93@\x82\x93\x82\x94\x82\x92\x82\x89\x82\x8e\x82\x87B'
p_ascii = r'[\x00-\x7f]'
p_hw_katakana = r'[\xa1-\xdf]' # half-width Katakana
p_jis208 = r'[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc]'
p_bad = r'.' # anything else
kinds = ['jis208', 'ascii', 'hwk', 'bad']
re_matcher = re.compile("(" + ")|(".join([p_jis208, p_ascii, p_hw_katakana, p_bad]) + ")")
for mobj in re_matcher.finditer(input_bytes):
s = mobj.group()
us = s.decode('shift-jis', 'replace')
print ("%-6s %-9s %-10r U+%04X %s"
% (kinds[mobj.lastindex - 1], mobj.span(), s, ord(us), unicodedata.name(us, '<no name>'))
)
jis208 (0, 2) '\x82s' U+FF34 FULLWIDTH LATIN CAPITAL LETTER T
jis208 (2, 4) '\x82\x88' U+FF48 FULLWIDTH LATIN SMALL LETTER H
jis208 (4, 6) '\x82\x89' U+FF49 FULLWIDTH LATIN SMALL LETTER I
jis208 (6, 8) '\x82\x93' U+FF53 FULLWIDTH LATIN SMALL LETTER S
ascii (8, 9) '@' U+0040 COMMERCIAL AT
jis208 (9, 11) '\x82\x89' U+FF49 FULLWIDTH LATIN SMALL LETTER I
jis208 (11, 13) '\x82\x93' U+FF53 FULLWIDTH LATIN SMALL LETTER S
ascii (13, 14) '@' U+0040 COMMERCIAL AT
jis208 (14, 16) '\x82@' U+FFFD REPLACEMENT CHARACTER
jis208 (16, 18) '\x82\x93' U+FF53 FULLWIDTH LATIN SMALL LETTER S
jis208 (18, 20) '\x82\x88' U+FF48 FULLWIDTH LATIN SMALL LETTER H
jis208 (20, 22) '\x82\x89' U+FF49 FULLWIDTH LATIN SMALL LETTER I
jis208 (22, 24) '\x82\x86' U+FF46 FULLWIDTH LATIN SMALL LETTER F
jis208 (24, 26) '\x82\x94' U+FF54 FULLWIDTH LATIN SMALL LETTER T
ascii (26, 27) '[' U+005B LEFT SQUARE BRACKET
jis208 (27, 29) '\x82\x8a' U+FF4A FULLWIDTH LATIN SMALL LETTER J
jis208 (29, 31) '\x82\x89' U+FF49 FULLWIDTH LATIN SMALL LETTER I
jis208 (31, 33) '\x82\x93' U+FF53 FULLWIDTH LATIN SMALL LETTER S
ascii (33, 34) '@' U+0040 COMMERCIAL AT
jis208 (34, 36) '\x82\x93' U+FF53 FULLWIDTH LATIN SMALL LETTER S
jis208 (36, 38) '\x82\x94' U+FF54 FULLWIDTH LATIN SMALL LETTER T
jis208 (38, 40) '\x82\x92' U+FF52 FULLWIDTH LATIN SMALL LETTER R
jis208 (40, 42) '\x82\x89' U+FF49 FULLWIDTH LATIN SMALL LETTER I
jis208 (42, 44) '\x82\x8e' U+FF4E FULLWIDTH LATIN SMALL LETTER N
jis208 (44, 46) '\x82\x87' U+FF47 FULLWIDTH LATIN SMALL LETTER G
ascii (46, 47) 'B' U+0042 LATIN CAPITAL LETTER B