Работа с нечитаемыми символами в текстовых файлах

  1. В файлах встречаются символы, нечитаемые ни в одной кодировке.

Например, есть csv файл с табличными данными и со столбцом, содержащим текстовую информацию, например, чат. В чате могут встретится символы (например, смайлик), которые не читаются с помощью библиотеки Pandas ни в одной кодировке. Прочитаем файл с нечитаемыми символами и разделим его на части.

# Импортируем необходимые библиотеки:
import io
import itertools
import csv
import pandas as pd
# Создадим пустые списки для данных и для заголовков:
data, head = [ ] , [ ]
href_f = ‘primer.csv’ # Ссылка на файл
k = len(open(href_f,encoding='utf-8-sig', errors = 'ignore').readlines()) # количество строк в файле
result_df=pd.DataFrame()
with io.open(href_f, encoding = 'utf-8-sig', errors = 'ignore') as f:
    mycsv=csv.reader( f ,  delimiter="~")
    for raw in itertools.islice(mycsv,0,1,1): # итерация для извлечения заголовка
        raw_text='~'.join(raw)
        head.append(raw_text.split('~'))
    for raw in itertools.islice(mycsv,0,k,1): # цикл чтения файла построчно, с шагом и  с определённого       
# места. На данном шаге если файл большой, можно разбивать его на части.
        raw_text='~  '.join(raw)
        data.append(raw_text.split('~')) 
result_df=pd.DataFrame(data)
result_df.columns=head
result_df

        При таком способе нечитаемые символы игнорируются, а для дальнейшей обработки создаются несколько датафреймов

  1. В тексте встречаются символы, читаемые в одной кодировке, но не читаемые в другой.

Примерами таких символов могут быть смайлики или греческие буквы. Такая задача может встретится, когда требуется из кодировки Юникода перекодировать в СР-1251 для импорта данных на Microsoft SQL Server. Ниже код, с помощью которого можно перекодировать символы.

Для начала определим две функции: первая заменяет один нечитаемый символ, вторая заменяет группу символов. Каждая функция обрабатывает одну из ошибок декодирования:

А) codec can’t encode character…

В таком случае для замены одного символа функция принимает строку и текст первой возможной ошибки, возникшей при декодировании.

Перед определением функции объявим глобальную переменную.

global  replace_parts  # глобальная переменная для хранения непечатных символов

replace_parts = []

def ex(e, line):
to_replace = re.findall(r"codec can't encode character\s(.*?)\s", str(e)) [0] 
if to_replace not in replace_parts:
replace_parts.append(to_replace) # добавляем в список не печатный символ
for to_replace in replace_parts: # бежим по всему спиcку и делаем замену
line = re.sub('\\'+to_replace.replace('\\', '').replace("'", ''), '', line) 
return lin

Б) codec can’t encode characters in position…

      Для замены группы символов функция принимает строку и текст второй возможной ошибки, возникшей при декодировании.

def ex2(e,line):

to_replace = re.findall(r"codec can't encode characters in position\s(.*?)\s", str(e))[0] 
to_replace_arr = to_replace.replace(':', '').split('-')
line = line[:int(to_replace_arr[0])] + line[int(to_replace_arr[1])+1:]
return line

Ниже приведён сам код, который перекодирует построчно файл из utf-8 в  cp1251

file_csv_name = ‘primer.csv’ # Ссылка на исходный файл   
           file_end_name = ‘out.txt’ # Ссылка на новый файл  
with open(file_csv_name, 'r', encoding = 'utf-8') as rp: # открытие исходного файла для чтения
    with open(file_end_name, 'w', encoding = 'cp1251') as fw: # открытие нового файла для записи     
        for tgt_line in rp: # построчный цикл
            q = 0 
            line = tgt_line
            while q == 0:   цикл работает, пока не избавимся от ошибок
                try: # декодирование строки, если ошибки нет, идем дальше
                    line = bytes(line, 'cp1251').decode('cp1251', 'ignore')
                    fw.writelines(line) # записываем строку в новый файл
                    q = 1
                    i = i + 1
                except Exception as e: # если одна из двух ошибок произошла
                    if 'characters in position' in str(e):                 
                        try:
                            line = ex2(e,line)
                            line = bytes(line, 'cp1251').decode('cp1251', 'ignore')
                            fw.writelines(line)
                            q = 1
                        except:
                            q = 0                
                    else: 
                        try:
                            line = ex(e,line)
                            line = bytes(line, 'cp1251').decode('cp1251', 'ignore')
                            fw.writelines(line)
                            q = 1
                        except:
                            q = 0 

Для демонстрации работы кода покажем, какие строчки в файле поменяются. Строка в текстовом файле «……Қ12…..» Строка ошибки: ‘charmap’ codec can’t encode character ‘\xcb’ in position 326: character maps to <undefined>. В итоге символ Қ у нас заменится на пустое место.

Итак, в этом посте были рассмотрены несколько способов чтения текстовых файлов формата csv, при наличии в них нечитаемых или не декодируемых символов.

https://t.me/python_job_interview – python собеседование

источник

Ответить