蟒蛇。通过url读取文件时的文件编码

问题描述 投票:2回答:2

我需要通过URL获取文件并返回该文件中具有最多单词计数的字符串。这是我的代码:

from urllib.request import urlopen

def wordiest_line(url):
    data = urlopen(url)

    if data:
        max_words = 0
        max_line = ""
        for line in data.readlines(): 
            #print(line)
            the_encoding = "utf-8"
            line = line.decode(the_encoding)
            line = line.rstrip()
            line_words = line.split()
            if len(line_words) > max_words:
                max_words = len(line_words)
                max_line = line

        #print("%s to RETURN\n" % max_line)
        return max_line

    else:
        return None

这些是用于测试此功能的一些URL:

  1. “Qazxswpoi”
  2. “Qazxswpoi”
  3. “Qazxswpoi”

对于链接1和3,它工作正常。但由于文件编码,http://math-info.hse.ru/f/2017-18/dj-prog/lines1.txt无法正常工作,因此西里尔文中有一些文字。

我试图定义什么字符串编码并解码它。这是代码:

http://lib.ru/FOUNDATION/3laws.txt_Ascii.txt

现在http://math-info.hse.ru/f/2017-18/dj-prog/lines2.txt失败并出现错误:'charmap'编解码器无法解码位置8中的字节0xdc:字符映射到undefined

其他网址仍然可以。你有什么建议如何修复它?

python encoding utf-8
2个回答
1
投票

如果您必须猜测或修复凌乱输入的编码,wordiest_line("http://lib.ru/FOUNDATION/3laws.txt_Ascii.txt")库可以节省生命。但是,在您的情况下,此信息是给出的 - 至少对于lib.ru示例。正如任何行为良好的服务器所期望的那样,纯文本响应的字符集在“Content-Type”标题中指定:

from urllib.request import urlopen
import chardet    

def wordiest_line(url):
    data = urlopen(url)

    if data:
        max_words = 0
        max_line = ""
        for line in data.readlines(): 
            #print(line)
            the_encoding = chardet.detect(line)['encoding']
            line = line.decode(the_encoding)
            #print(the_encoding, line)
            line = line.rstrip()
            line_words = line.split()
            if len(line_words) > max_words:
                max_words = len(line_words)
                max_line = line

        #print("%s to RETURN\n" % max_line)
        return max_line

    else:
        return None

注意:我假设您使用的是Python 3;上面的代码在Python 2中不起作用。另外,我建议你在迭代文件的行之前对内容进行解码,假设你不会像使用不同编码行的严重混乱的文件那样给出破坏的输入。

第二个注意事项:wordiest_line("http://lib.ru/FOUNDATION/3laws.txt_Ascii.txt")库可能允许您为此任务编写较少的样板代码。

第三点:对于计算单词,chardet相当简单。例如,“争论”和“争辩”将被视为不同的单词,您甚至可能希望将“争论”和“争论”定义为属于同一个单词。在这种情况下,您将不得不使用NLP库,例如NLTK或SpaCy。


0
投票

Python允许你使用`decode(encoding,'replace')进行容错解码,用正式的U + FFFD REPLACEMENT CHARACTER替换任何有问题的字符。

如果不确定编码(如果@lenz提出的解决方案不方便),你应该使用:

import codecs
from urllib.request import urlopen

def wordiest_line(url):
    resp = urlopen(url)
    charset = resp.headers.get_content_charset()
    textreader = codecs.getreader(charset)(resp)
    for line in textreader:
        line = line.rstrip()
        # continue with tokenising and counting...

即使使用utf8编码,它也能识别正确的行,但当然无法正确解码

或者,您可以使用Latin1编码将任何字节转换为相同代码值的unicode字符这一事实。在这里你可以做到:

requests

这不仅可以正确识别正确的行,还可以:

line.split()

你得到原始字节的原始行,可以检查它现在正确解码它。

顺便说一句,该文件的正确编码是KOI8-R

© www.soinside.com 2019 - 2024. All rights reserved.