如何下载任何(!)的网页与蟒蛇正确的字符集?(How to download any(!) webp

2019-07-20 03:17发布

问题

当使用python屏幕抓取网页人们必须知道页面的字符编码。 如果你的字符编码错误比你的输出就会搞砸。

人们通常使用一些基本的技术检测的编码。 它们既可以使用的字符集从首部或在元标记中定义的字符集,或者它们使用一个编码检测器 (其不关心元标记或报头)。 通过只使用一个这些技术,有时你不会得到结果,你会在浏览器中一样。

浏览器做这种方式:

  • Meta标签总是优先(或XML定义)
  • 在报头中定义的编码被用来在没有在一个元标记定义的字符集
  • 如果编码未在所有已定义的,比它的时间用于编码检测。

(嗯......至少这是我相信的样子大多数浏览器做到这一点。文档非常稀少。)

我正在寻找的是能够确定该字符集的网页的方式浏览器将一个库。 我敢肯定,我不是谁需要对这个问题的妥善解决办法第一。

解决方案(我还没有尝试过呢...)

据美丽的汤的文档 。

美丽的汤尝试以下编码,依次排列,把你的文件转换为Unicode:

  • 编码你传递的fromEncoding参数的构造函数汤。
  • 或者例如,在一个XML声明(HTML文档)一个http-当量META标记:在文档中发现的编码。 如果美丽的汤发现文档中这种编码,它再次从头开始分析文档,并给出了新的编码一试。 唯一的例外是,如果你明确指定的编码,而该编码实际工作:那么它会忽略它找到的文档中的任何编码。
  • 编码通过查看文件的前几个字节嗤之以鼻。 如果编码在此阶段检测到,这将是UTF-*编码,EBCDIC,或ASCII之一。
  • 编码通过在chardet库嗅,如果你已经安装了它。
  • UTF-8
  • Windows的1252

Answer 1:

我会用html5lib这一点。



Answer 2:

当您下载使用的urllib或urllib2的一个文件,你可以找到一个charset头是否被传送:

fp = urllib2.urlopen(request)
charset = fp.headers.getparam('charset')

您可以使用BeautifulSoup来定位HTML meta元素:

soup = BeatifulSoup.BeautifulSoup(data)
meta = soup.findAll('meta', {'http-equiv':lambda v:v.lower()=='content-type'})

如果两者都不是可用的,浏览器通常回落到用户配置,具有自动检测相结合。 作为rajax建议,你可以使用在chardet模块。 如果您有可用告诉你用户配置的页面应该是中国(说),你可以做的更好。



Answer 3:

使用通用编码探测器 :

>>> import chardet
>>> chardet.detect(urlread("http://google.cn/"))
{'encoding': 'GB2312', 'confidence': 0.99}

另一种选择是只使用wget:

  import os
  h = os.popen('wget -q -O foo1.txt http://foo.html')
  h.close()
  s = open('foo1.txt').read()


Answer 4:

好像你需要给出答案的混合体:

  1. 使用urllib的抓取网页
  2. 查找<meta>用美丽的汤或其他方法标记
  3. 如果不存在meta标签,检查通过的urllib返回头
  4. 如果仍然不给你一个答案,使用通用编码探测器。

老实说,我不相信你会找到什么比这更好的。

如果您还读入你在对方的回答的评论链接到FAQ事实上,这也正是探测器库倡导的作者。

如果您认为FAQ,这是浏览器做什么(在你原来的问题要求)作为检测器是火狐嗅探代码的端口。



Answer 5:

Scrapy下载页面,并检测正确的编码它,不像requests.get(URL)的.text或的urlopen。 要做到这一点,试图遵循类似浏览器的规则 - 这是最好的人能做到的,因为网站所有者有激励,使他们的网站在浏览器中运行。 Scrapy需要采取HTTP头, <meta>标记,BOM标记和差异在帐户编码名称。

基于内容的猜测(chardet的,UnicodeDammit)对自己是不是一个正确的解决方案,因为它可能会失败; 它应该在标题或仅作为最后的手段<meta>或BOM标记不可用或提供任何信息。

您不必使用Scrapy得到它的编码检测功能; 他们是在一个单独的库调用w3lib释放(其中有一些其他的东西): https://github.com/scrapy/w3lib 。

要获得页面的编码和Unicode身体使用w3lib.encoding.html_to_unicode功能,可以与基于内容的后备猜测:

import chardet
from w3lib.encoding import html_to_unicode

def _guess_encoding(data):
    return chardet.detect(data).get('encoding')

detected_encoding, html_content_unicode = html_to_unicode(
    content_type_header,
    html_content_bytes,
    default_encoding='utf8', 
    auto_detect_fun=_guess_encoding,
)


Answer 6:

而不是试图获得一个页面,然后找出字符集的浏览器会用,为什么不直接使用浏览器抓取网页和检查什么字符集,它使用..

from win32com.client import DispatchWithEvents
import threading


stopEvent=threading.Event()

class EventHandler(object):
    def OnDownloadBegin(self):
        pass

def waitUntilReady(ie):
    """
    copypasted from
    http://mail.python.org/pipermail/python-win32/2004-June/002040.html
    """
    if ie.ReadyState!=4:
        while 1:
            print "waiting"
            pythoncom.PumpWaitingMessages()
            stopEvent.wait(.2)
            if stopEvent.isSet() or ie.ReadyState==4:
                stopEvent.clear()
                break;

ie = DispatchWithEvents("InternetExplorer.Application", EventHandler)
ie.Visible = 0
ie.Navigate('http://kskky.info')
waitUntilReady(ie)
d = ie.Document
print d.CharSet


Answer 7:

BeautifulSoup这剂与UnicodeDammit: Unicode的,该死



文章来源: How to download any(!) webpage with correct charset in python?