为了完整起见,BeautifulSoup 4 版本也使用了服务器提供的编码:
from bs4 import BeautifulSoup
import urllib.request
parser = 'html.parser' # or 'lxml' (preferred) or 'html5lib', if installed
resp = urllib.request.urlopen("http://www.gpsbasecamp.com/national-parks")
soup = BeautifulSoup(resp, parser, from_encoding=resp.info().get_param('charset'))
for link in soup.find_all('a', href=True):
print(link['href'])
或 Python 2 版本:
from bs4 import BeautifulSoup
import urllib2
parser = 'html.parser' # or 'lxml' (preferred) or 'html5lib', if installed
resp = urllib2.urlopen("http://www.gpsbasecamp.com/national-parks")
soup = BeautifulSoup(resp, parser, from_encoding=resp.info().getparam('charset'))
for link in soup.find_all('a', href=True):
print link['href']
还有一个使用requests library 的版本,正如所写的那样,它可以在 Python 2 和 3 中工作:
from bs4 import BeautifulSoup
from bs4.dammit import EncodingDetector
import requests
parser = 'html.parser' # or 'lxml' (preferred) or 'html5lib', if installed
resp = requests.get("http://www.gpsbasecamp.com/national-parks")
http_encoding = resp.encoding if 'charset' in resp.headers.get('content-type', '').lower() else None
html_encoding = EncodingDetector.find_declared_encoding(resp.content, is_html=True)
encoding = html_encoding or http_encoding
soup = BeautifulSoup(resp.content, parser, from_encoding=encoding)
for link in soup.find_all('a', href=True):
print(link['href'])
soup.find_all('a', href=True) 调用查找所有具有href 属性的<a> 元素;没有该属性的元素会被跳过。
BeautifulSoup 3 于 2012 年 3 月停止开发;新项目确实应该始终使用 BeautifulSoup 4。
请注意,您应该将 HTML 从字节解码到 BeautifulSoup。您可以通知 BeautifulSoup 在 HTTP 响应标头中找到的字符集以帮助解码,但是这个 可能 是错误的并且与 HTML 本身中的 <meta> 标头信息冲突,这就是为什么上面使用 BeautifulSoup 内部类方法EncodingDetector.find_declared_encoding() 来确保此类嵌入的编码提示能够胜过配置错误的服务器。
对于requests,如果响应具有text/* mimetype,则response.encoding 属性默认为Latin-1,即使没有返回字符集。这与 HTTP RFC 一致,但在与 HTML 解析一起使用时会很痛苦,因此当 Content-Type 标头中未设置 charset 时,您应该忽略该属性。