인코딩 된 텍스트를 받았지만 어떤 문자 집합이 사용되었는지 알 수 없습니다. 파이썬을 사용하여 텍스트 파일의 인코딩을 결정하는 방법이 있습니까? C #을 처리 하는 텍스트 파일의 인코딩 / 코드 페이지를 어떻게 감지합니까 ?
답변
인코딩을 항상 올바르게 감지하는 것은 불가능 합니다.
(chardet FAQ에서 🙂
그러나 일부 인코딩은 특정 언어에 최적화되어 있으며 언어는 임의적이지 않습니다. 일부 문자 시퀀스는 항상 팝업되지만 다른 시퀀스는 의미가 없습니다. 신문을 개봉하고 “txzqJv 2! dasd0a QqdKjvz”를 발견 한 영어에 능숙한 사람은 영어가 아님을 완전히 인식합니다 (영어로만 구성되어 있음에도 불구하고). 많은 “일반적인”텍스트를 연구함으로써 컴퓨터 알고리즘은 이러한 유창함을 시뮬레이션하고 텍스트 언어에 대한 교육 된 추측을 할 수 있습니다.
이 연구를 사용하여 인코딩을 감지 하는 chardet 라이브러리가 있습니다. chardet은 Mozilla 자동 감지 코드의 포트입니다.
UnicodeDammit 을 사용할 수도 있습니다 . 다음 방법을 시도합니다.
- 문서 자체에서 발견 된 인코딩 (예 : XML 선언 또는 http-equiv META 태그) Beautiful Soup이 문서 내에서 이런 종류의 인코딩을 찾으면 처음부터 문서를 다시 구문 분석하고 새 인코딩을 시도합니다. 인코딩을 명시 적으로 지정하고 해당 인코딩이 실제로 작동 한 경우는 예외입니다. 문서에서 찾은 인코딩은 무시됩니다.
- 파일의 처음 몇 바이트를보고 스니핑 된 인코딩입니다. 이 단계에서 인코딩이 감지되면 UTF- * 인코딩, EBCDIC 또는 ASCII 중 하나가됩니다.
- chardet 라이브러리에 의해 인코딩 된 인코딩 ( 설치된 경우)
- UTF-8
- 윈도우 -1252
답변
인코딩 작업을위한 또 다른 옵션은
libmagic ( 파일 명령 뒤에있는 코드
)을 사용하는 것입니다. 사용 가능한 파이썬 바인딩이 풍부합니다.
파일 소스 트리에있는 파이썬 바인딩은
python-magic (또는 python3-magic ) 데비안 패키지로 제공됩니다. 다음을 수행하여 파일 인코딩을 결정할 수 있습니다.
import magic
blob = open('unknown-file', 'rb').read()
m = magic.open(magic.MAGIC_MIME_ENCODING)
m.load()
encoding = m.buffer(blob) # "utf-8" "us-ascii" etc
pypi에도 동일한 이름이지만 호환되지 않는 python-magic pip 패키지가 있습니다 libmagic
. 다음을 수행하여 인코딩을 가져올 수도 있습니다.
import magic
blob = open('unknown-file', 'rb').read()
m = magic.Magic(mime_encoding=True)
encoding = m.from_buffer(blob)
답변
일부 인코딩 전략은 다음과 같이 맛보십시오.
#!/bin/bash
#
tmpfile=$1
echo '-- info about file file ........'
file -i $tmpfile
enca -g $tmpfile
echo 'recoding ........'
#iconv -f iso-8859-2 -t utf-8 back_test.xml > $tmpfile
#enca -x utf-8 $tmpfile
#enca -g $tmpfile
recode CP1250..UTF-8 $tmpfile
루프 형태로 파일을 열어서 인코딩을 확인하고 싶을 수도 있지만 먼저 파일 크기를 확인해야 할 수도 있습니다.
encodings = ['utf-8', 'windows-1250', 'windows-1252' ...etc]
for e in encodings:
try:
fh = codecs.open('file.txt', 'r', encoding=e)
fh.readlines()
fh.seek(0)
except UnicodeDecodeError:
print('got unicode error with %s , trying different encoding' % e)
else:
print('opening the file with encoding: %s ' % e)
break
답변
다음은 파일이 큰 경우 파일에서 chardet
읽는 인코딩 예측 을 액면 값에서 읽고 취하는 예입니다 n_lines
.
chardet
또한 confidence
인코딩 예측의 가능성 (즉, 어떻게 될지 찾지 못했음)을 제공합니다.이 예측은에서 예측과 함께 반환 chardet.predict()
되므로 원하는 경우 어떻게 든 작동 할 수 있습니다.
def predict_encoding(file_path, n_lines=20):
'''Predict a file's encoding using chardet'''
import chardet
# Open the file as binary data
with open(file_path, 'rb') as f:
# Join binary lines for specified number of lines
rawdata = b''.join([f.readline() for _ in range(n_lines)])
return chardet.detect(rawdata)['encoding']
답변
# Function: OpenRead(file)
# A text file can be encoded using:
# (1) The default operating system code page, Or
# (2) utf8 with a BOM header
#
# If a text file is encoded with utf8, and does not have a BOM header,
# the user can manually add a BOM header to the text file
# using a text editor such as notepad++, and rerun the python script,
# otherwise the file is read as a codepage file with the
# invalid codepage characters removed
import sys
if int(sys.version[0]) != 3:
print('Aborted: Python 3.x required')
sys.exit(1)
def bomType(file):
"""
returns file encoding string for open() function
EXAMPLE:
bom = bomtype(file)
open(file, encoding=bom, errors='ignore')
"""
f = open(file, 'rb')
b = f.read(4)
f.close()
if (b[0:3] == b'\xef\xbb\xbf'):
return "utf8"
# Python automatically detects endianess if utf-16 bom is present
# write endianess generally determined by endianess of CPU
if ((b[0:2] == b'\xfe\xff') or (b[0:2] == b'\xff\xfe')):
return "utf16"
if ((b[0:5] == b'\xfe\xff\x00\x00')
or (b[0:5] == b'\x00\x00\xff\xfe')):
return "utf32"
# If BOM is not provided, then assume its the codepage
# used by your operating system
return "cp1252"
# For the United States its: cp1252
def OpenRead(file):
bom = bomType(file)
return open(file, 'r', encoding=bom, errors='ignore')
#######################
# Testing it
#######################
fout = open("myfile1.txt", "w", encoding="cp1252")
fout.write("* hi there (cp1252)")
fout.close()
fout = open("myfile2.txt", "w", encoding="utf8")
fout.write("\u2022 hi there (utf8)")
fout.close()
# this case is still treated like codepage cp1252
# (User responsible for making sure that all utf8 files
# have a BOM header)
fout = open("badboy.txt", "wb")
fout.write(b"hi there. barf(\x81\x8D\x90\x9D)")
fout.close()
# Read Example file with Bom Detection
fin = OpenRead("myfile1.txt")
L = fin.readline()
print(L)
fin.close()
# Read Example file with Bom Detection
fin = OpenRead("myfile2.txt")
L =fin.readline()
print(L) #requires QtConsole to view, Cmd.exe is cp1252
fin.close()
# Read CP1252 with a few undefined chars without barfing
fin = OpenRead("badboy.txt")
L =fin.readline()
print(L)
fin.close()
# Check that bad characters are still in badboy codepage file
fin = open("badboy.txt", "rb")
fin.read(20)
fin.close()
답변
귀하의 플랫폼에 따라 linux shell file
명령 을 사용하기로 선택했습니다 . Linux 시스템 중 하나에서 독점적으로 실행되는 스크립트에서 사용하기 때문에 이것은 나를 위해 작동합니다.
분명히 이것은 이상적인 솔루션이나 답변이 아니지만 필요에 맞게 수정할 수 있습니다. 제 경우에는 파일이 UTF-8인지 아닌지를 결정하기 만하면됩니다.
import subprocess
file_cmd = ['file', 'test.txt']
p = subprocess.Popen(file_cmd, stdout=subprocess.PIPE)
cmd_output = p.stdout.readlines()
# x will begin with the file type output as is observed using 'file' command
x = cmd_output[0].split(": ")[1]
return x.startswith('UTF-8')
답변
도움이 될 수 있습니다.
from bs4 import UnicodeDammit
with open('automate_data/billboard.csv', 'rb') as file:
content = file.read()
suggestion = UnicodeDammit(content)
suggestion.original_encoding
#'iso-8859-1'