php网页抓取乱码(怎么自动获取网页的编码格式?的urlopen方法返回一个 )
优采云 发布时间: 2022-03-14 19:02php网页抓取乱码(怎么自动获取网页的编码格式?的urlopen方法返回一个
)
在对爬虫获取的网页进行处理之前,我们需要知道被爬取的网页的编码格式,然后才能正确解码,编码成目标格式保存或者进行后续的文本处理。尤其是在多语言环境中,获取正确的网页编码格式尤为重要。
我们可以手动查看网页源码中meta标签下的content属性,其中charset代表网页的编码格式。所谓爬虫,本质上是一个自动化程序,那么如何自动获取网页的编码格式呢?python的urlopen方法返回一个响应对象,响应的info方法可以返回与url相关的元信息,包括内容格式、长度等信息。如下所示:
貌似只要使用getparam('charset')就可以成功获取到网页编码格式,可惜服务器返回的元信息并不是都收录charset,info中的信息依赖于爬取的url服务器上的爬虫。另外,即使你确定你的爬虫爬取的部分服务器会返回charset信息,也不能保证网页的编码格式一定要和charset一致。因此,最安全的做法是直接探测服务器返回的文本的编码格式。我在这里使用 python 中的 chardet 包。chardet的detect方法可以检测传入字符串的编码格式并给出检测精度。
import urllib2
import chardet
import time
response = urllib2.urlopen('http://www.simmerchan.me/')
content = response.read()
t = time.time()
charset_info = chardet.detect(content)
print charset_info
print charset_info['encoding']
print time.time()-t
{'confidence': 0.99, 'encoding': 'utf-8'}
utf-8
0.468999862671
当获取的网页内容比较大时,使用上述方法检测编码是相当耗时的。一种可能的方法是检测内容片段。
import urllib2
import chardet
import time
response = urllib2.urlopen('http://www.simmerchan.me/')
content = response.read()
t = time.time()
charset_info = chardet.detect(content[:70000])
print charset_info
print charset_info['encoding']
print time.time()-t
{'confidence': 0.99, 'encoding': 'utf-8'}
utf-8
0.114000082016
分片的大小取决于具体的应用场景。在我自己的爬虫项目中,400可以处理大部分的登陆页面。我这里取7000是因为我的网页源码中之前的大部分内容都不收录中文。如果我取 6000,它会被检测为 ascii 码。我也想过取中间段的可能性,比如6000到7000,9000到10000,前者结果是utf-8,准确率是0.99,后者是ISO-8859-2,准确率0.82,事实证明这种方法无效,随机性太大。
获取网页编码格式后,我们可以对网页内容进行解码,然后编码成统一的格式进行处理。
import urllib2
import chardet
import time
response = urllib2.urlopen('http://www.simmerchan.me/')
content = response.read()
t = time.time()
charset = chardet.detect(content[:400])['encoding']
content = content.decode(charset, 'ignore').encode('utf-8')
ignore 参数是忽略那些无法解码成 unicode 的字符。如果不加这个参数,可能会出现类似如下的错误
UnicodeDecodeError: 'gb2312' codec can't decode bytes in position 61399-61400: illegal multibyte sequence