Cha*_*man 5 encoding utf-8 sys python-3.x
我正在尝试使用cURL和Python的BeautifulSoup库编写一个(非常)基本的Web搜寻器(因为它比GNU awk和一堆正则表达式更容易理解)。
目前,我正在尝试使用cURL(即curl http://www.example.com/ | ./parse-html.py)将网页的内容通过管道传递给程序
由于某种原因,Python会UnicodeDecodeError因为一个无效的起始字节而抛出a (我已经看过这个答案以及关于无效起始字节的这个答案,但没有弄清楚如何从中解决问题)。
具体来说,我尝试a.encode('utf-8').split()从第一个答案开始使用。第二个答案只是说明了问题(Python发现无效的启动字节),尽管它没有给出解决方案。
我试图将cURL的输出重定向到文件(即,curl http://www.example.com/ > foobar.html修改程序以接受文件作为命令行参数,尽管这样做会导致相同的结果UnicodeDecodeError。)
我检查了一下,据我所知,locale charmapis 的输出UTF-8表示我的系统正在编码字符UTF-8(这使我对此感到特别困惑UnicodeDecodeError。
目前,导致错误的确切行是html_doc = sys.stdin.readlines().encode('utf-8').strip()。我尝试将其重写为for循环,尽管遇到了同样的问题。
到底是什么引起的UnicodeDecodeError,我应该如何解决?
编辑:
通过更改行html_doc = sys.stdin.readlines().encode('utf-8').strip()来html_doc = sys.stdin解决此问题
问题出在读取过程中,而不是编码过程中;输入资源根本不是用 UTF-8 编码的,而是另一种编码。在 UTF-8 shell 中,您可以轻松地重现该问题
\n\n$ echo 2\xc2\xa5 | iconv -t iso8859-1 | python3 -c \'import sys;sys.stdin.readline()\'\nTraceback (most recent call last):\n File "<string>", line 1, in <module>\n File "/usr/lib/python3.5/codecs.py", line 321, in decode\n (result, consumed) = self._buffer_decode(data, self.errors, final)\nUnicodeDecodeError: \'utf-8\' codec can\'t decode byte 0xa5 in position 1: invalid start byte\nRun Code Online (Sandbox Code Playgroud)\n\n您可以将文件(sys.stdin.buffer.read()、 或with open(..., \'rb\') as f: f.read())作为二进制读取(您将获得一个bytes对象),检查它并猜测编码。HTML 标准中记录了执行此操作的实际算法。
然而,在许多情况下,编码不是在文件本身中指定的,而是通过 HTTP Content-Typeheader指定的。不幸的是,您对curl 的调用没有捕获此标头。您可以只使用Python,而不是使用curl和Python——它已经可以下载URL了。从 youtube-dl窃取编码检测算法,我们得到如下内容:
import re\nimport urllib.request\n\n\ndef guess_encoding(content_type, webpage_bytes):\n m = re.match(\n r\'[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+\\s*;\\s*charset="?([a-zA-Z0-9_-]+)"?\',\n content_type)\n if m:\n encoding = m.group(1)\n else:\n m = re.search(br\'<meta[^>]+charset=[\\\'"]?([a-zA-Z0-9_-]+)[ /\\\'">]\',\n webpage_bytes[:1024])\n if m:\n encoding = m.group(1).decode(\'ascii\')\n elif webpage_bytes.startswith(b\'\\xff\\xfe\'):\n encoding = \'utf-16\'\n else:\n encoding = \'utf-8\'\n\n return encoding\n\n\ndef download_html(url):\n with urllib.request.urlopen(url) as urlh:\n content = urlh.read()\n encoding = guess_encoding(urlh.getheader(\'Content-Type\'), content)\n return content.decode(encoding)\n\nprint(download_html(\'https://phihag.de/2016/iso8859.php\'))\nRun Code Online (Sandbox Code Playgroud)\n\n还有一些库(尽管不在标准库中)支持开箱即用,即requests。
\n\n我还建议您阅读编码的基础知识。
\n| 归档时间: |
|
| 查看次数: |
1200 次 |
| 最近记录: |