4
votes

Comment trouver / remplacer des caractères non imprimables / non-ascii en utilisant Python 3?

J'ai un fichier, des lignes dans un fichier .csv qui bloquent une importation de base de données à cause de caractères géniaux dans certains champs de la ligne.

J'ai recherché, trouvé des articles sur la façon de remplacer les caractères non-ascii dans Python 3, mais rien ne fonctionne.

Quand j'ouvre le fichier dans vi et que je fais: set list, il y a un $ à la fin d'une ligne là où il ne devrait pas y en avoir, et ^ I ^ I at le début de la ligne suivante. Les deux lignes doivent être une seule ligne jointe et non ^ I là. Je sais que $ est la fin de la ligne '\ n' et j'ai essayé de les remplacer, mais rien ne fonctionne.

Je ne sais pas ce que ^ je représente, peut-être un onglet.

J'ai essayé cette fonction en vain:

37 Cancelled,01-19-17,,basket,00-00-00,00-00-00,,,,98533,SingleSource,,,17035 Cherry Hill Dr,"L/o 1-19-17 @ 11:45am$
38 ^I^IVictorville",SAN BERNARDINO,CA,92395,,,,,0,,,,,Lock:6111 ,,,No,No,,0.00,0.00,No,01-19-17,0.00,0.00,,01-19-17,00-00-00,,provider,,,Unread,00-00-00,,$

Y a-t-il un outil qui me montrera exactement ce qu'est ce personnage offensant, puis trouver une méthode pour le remplacer?

J'ouvre le fichier comme tel (le .csv a été enregistré en UTF-8)

f_csv_in = open(csv_in, "r", encoding="utf-8")

Voici deux lignes qui devraient être une avec le problème des caractères non-ascii visibles.

Ces deux lignes devraient être une seule ligne. Remarquez le $ à la fin de la ligne 37, et la ligne 38 commence par ^ I ^ I.

Une partie du problème, que vi montre, est qu'il y a une nouvelle ligne $ sur la ligne 37 où je ne veux pas que ce soit. Cela devrait être une ligne.

def remove_non_ascii(text):
    new_text = re.sub(r"[\n\t\r]", "", text)
    new_text = ''.join(new_text.split("\n"))
    new_text = ''.join([i if ord(i) < 128 else ' ' for i in new_text])
    new_text = "".join([x for x in new_text if ord(x) < 128])
    new_text = re.sub(r'[^\x00-\x7F]+', ' ', new_text)
    new_text = new_text.rstrip('\r\n')
    new_text = new_text.strip('\n')
    new_text = new_text.strip('\r')
    new_text = new_text.strip('\t')
    new_text = new_text.replace('\n', '')
    new_text = new_text.replace('\r', '')
    new_text = new_text.replace('\t', '')
    new_text = filter(lambda x: x in string.printable, new_text)
    new_text = "".join(list(new_text))

    return new_text


3 Réponses :


1
votes

Un moyen simple de supprimer les caractères non-ascii pourrait être de faire:

new_text = "".join([c for c in text if c.isascii()])

NB: Si vous lisez ce texte à partir d'un fichier, assurez-vous de le lire avec le bon encodage


5 commentaires

J'ai essayé cet extrait de code, mais je n'ai pas réussi. Le fichier .csv a été enregistré au format UTF-8, je l'ouvre comme ceci. f_csv_in = ouvert (csv_in, "r")


Essayez avec f_csv_in = open (csv_in, "r", encoding = 'utf-8')


Pas de chance pour l'instant avec l'ouverture avec encoding = 'utf-8'. Sur 150K lignes dans le fichier .csv, il y en a 162 qui contiennent un caractère qui raccroche, les autres près de 150K lignes sont OK.


Utilisez-vous Linux? Si vous exécutez file csv_in quel est le codage signalé?


J'utilise cygwin sous Windows. J'utilise Python sous cygwin. Le fichier a été enregistré au format UTF-8 .csv à l'aide d'Excel. Il est ouvert en Python avec encoding = 'utf-8'



2
votes

6 commentaires

Sur la base de vos commentaires, j'ai ajouté ces deux lignes à la méthode: remove_non_ascii (texte), sans succès. new_text = filter (lambda x: x dans string.printable, new_text) new_text = "" .join (list (new_text)) `` `


Pouvez-vous ouvrir votre fichier dans un autre éditeur de texte? Les personnages sont-ils toujours là? Pouvez-vous fournir quelques exemples de lignes pour travailler avec des données réelles?


Je peux ouvrir le fichier dans un éditeur de texte, je peux l'ouvrir dans vi. Quand je tape: set list dans vi, je vois qu'il y a un $ à la fin de la ligne, là où il ne devrait pas y en avoir. La ligne ci-dessous commence par ^ I (contrôle I), deux d'entre eux à la suite. Les deux lignes doivent être jointes à une seule ligne sans $ à la fin de la première et sans ^ I ^ I à n'importe quel point de la ligne. Je peux fournir une ligne avec laquelle travailler, mais comment?


Vi est censé afficher $ lorsque vous tapez : set list pour indiquer les fins de ligne, ce n'est donc pas une erreur. Il n'y a pas de caractère «réel» à supprimer, c'est juste un style vi pour la fin de ligne. En ce qui concerne le ^ | , par quoi vos fichiers csv sont-ils délimités?


Vous trouverez ci-dessous deux lignes qui devraient être une seule avec des caractères non ascii visibles. Ces deux lignes doivent être une seule ligne. Notez le $ à la fin de la ligne 37 et la ligne 38 commence par ^ I ^ I. le problème, que montre vi, est qu'il y a une nouvelle ligne $ à la ligne 37 où je ne veux pas qu'elle soit. devrait être une ligne. 37 Annulé, 01-19-17, panier, 00-00-00,00-00-00 , 98533, Source unique , 17035 Cherry Hill Dr, "L / o 1-19 -17 @ 11:45 am$ 38 ^ I ^ IVictorville ", SAN BERNARDINO, CA, 92395 , 0 , Verrouillage: 6111 , Non, Non , 0,00,0,00, Non, 01- 19-17,0.00,0.00`` 01-19-17,00-00-00‌ , provider , Non lu, ‌ 00-00-00 , $


Rien ne semble fonctionner. Je ne sais pas ce qu'il y a dans ces lignes errantes qui bloquent les choses. Rien ne semble fonctionner pour remplacer le caractère de nouvelle ligne au milieu de la ligne ou pour remplacer les caractères de contrôle ^ I. Aucune fonction Python ne semble fonctionner. J'ai essayé des dizaines d'approches différentes.



0
votes

Il semble que vous ayez un fichier csv qui contient des valeurs entre guillemets, c'est-à-dire des valeurs telles que des virgules incorporées ou des retours à la ligne qui doivent être entourées de guillemets pour que les lecteurs csv les gèrent correctement.

Si vous regardez les données d'exemple, vous pouvez voir qu'il y a un guillemet ouvrant mais pas de guillemet fermant à la fin de la première ligne, et un guillemet double fermant sans guillemet ouvrant sur la deuxième ligne, indiquant que les guillemets contiennent une valeur avec une nouvelle ligne intégrée.

Le fait que les lignes soient coupées en deux peut être un artefact de l'application utilisée pour les visualiser, ou du code qui les traite: si le logiciel ne comprend pas le csv, il le fera supposons que chaque caractère de nouvelle ligne indique une nouvelle ligne.

On ne sait pas exactement quel problème cela cause dans la base de données, mais il est fort probable que les guillemets - en particulier les guillemets sans correspondance - puissent causer un problème, en particulier si le les données ne sont pas correctement échappées avant l'insertion.

Cet extrait de code réécrit le fichier, supprimant les virgules incorporées, les retours à la ligne et les tabulations, et indique à l'écrivain de ne citer aucune valeur. Il échouera avec le message d'erreur _csv.Error: need to escape, but no escapechar set s'il trouve une valeur qui doit être échappée. En fonction de vos données, vous devrez peut-être ajuster le modèle de regex.

with open('lines.csv') as f, open('fixed.csv', 'w') as out:
    reader = csv.reader(f)
    writer = csv.writer(out, quoting=csv.QUOTE_NONE)
    for line in reader:
        new_row = [re.sub(r'\t|\n|,', ' ', x) for x in line]
        writer.writerow(new_row)


0 commentaires