- 有些标签可以内嵌 如:BLOCKQUOTE,有些不行 如:P
- table和list标签有一个自然的内嵌顺序。例如,TD标签内为TR标签,而不会相反。
- SCRIPT 标签的内容不会被剖析为HTML。
- META 标签可以知道文档的编码类型。
- 这是运行例子:
- from BeautifulSoup import BeautifulSoup
- html = "<html><p>Para 1<p>Para 2<blockquote>Quote 1<blockquote>Quote 2"
- soup = BeautifulSoup(html)
- print soup.prettify()
- # <html>
- # <p>
- # Para 1
- # </p>
- # <p>
- # Para 2
- # <blockquote>
- # Quote 1
- # <blockquote>
- # Quote 2
- # </blockquote>
- # </blockquote>
- # </p>
- # </html>
注意:
BeautifulSoup
会智能判断那些需要添加关闭标签的位置,即使原始的文档没有。
也就是说那个文档不是一个有效的HTML,但是它也不是太糟糕。下面是一个比较糟糕的文档。在一些问题中,它的<FORM>的开始在 <TABLE> 外面,结束在<TABLE>里面。 (这种HTML在一些大公司的页面上也屡见不鲜)
- from BeautifulSoup import BeautifulSoup
- html = """
- <html>
- <form>
- <table>
- <td><input name="input1">Row 1 cell 1
- <tr><td>Row 2 cell 1
- </form>
- <td>Row 2 cell 2<br>This</br> sure is a long cell
- </body>
- </html>"""
Beautiful Soup 也可以处理这个文档:
- print BeautifulSoup(html).prettify()
- # <html>
- # <form>
- # <table>
- # <td>
- # <input name="input1" />
- # Row 1 cell 1
- # </td>
- # <tr>
- # <td>
- # Row 2 cell 1
- # </td>
- # </tr>
- # </table>
- # </form>
- # <td>
- # Row 2 cell 2
- # <br />
- # This
- # sure is a long cell
- # </td>
- # </html>
剖析 XML
BeautifulSoup
类似浏览器,是个具有启发性的类,可以尽可能的推测HTML文档作者的意图。但是XML没有固定的标签集合,因此这些启发式的功能没有作用。因此 BeautifulSoup
处理XML不是很好。
使用BeautifulStoneSoup
类剖析XML文档。它是一个概括的类,没有任何特定的XML方言已经简单的标签内嵌规则。下面是范例:
- from BeautifulSoup import BeautifulStoneSoup
- xml = "<doc><tag1>Contents 1<tag2>Contents 2<tag1>Contents 3"
- soup = BeautifulStoneSoup(xml)
- print soup.prettify()
- # <doc>
- # <tag1>
- # Contents 1
- # <tag2>
- # Contents 2
- # </tag2>
- # </tag1>
- # <tag1>
- # Contents 3
- # </tag1>
- # </doc>
BeautifulStoneSoup
的一个主要缺点就是它不知道如何处理自结束标签 。 HTML 有固定的自结束标签集合,但是XML取决对应的DTD文件。你可以通过传递selfClosingTags
的参数的名字到 BeautifulStoneSoup
的构造器中,指定自结束标签:- from BeautifulSoup import BeautifulStoneSoup
- xml = "<tag>Text 1<selfclosing>Text 2"
- print BeautifulStoneSoup(xml).prettify()
- # <tag>
- # Text 1
- # <selfclosing>
- # Text 2
- # </selfclosing>
- # </tag>
- print BeautifulStoneSoup(xml, selfClosingTags=['selfclosing']).prettify()
- # <tag>
- # Text 1
- # <selfclosing />
- # Text 2
- # </tag>
如果它不工作
这里有 一些其他的剖析类 使用与上述两个类不同的智能感应。你也可以子类化以及定制一个剖析器 使用你自己的智能感应方法。使用Unicode的Beautiful Soup,Dammit
当你的文档被剖析之后,它就自动被转换为unicode。 Beautiful Soup 只存储Unicode字符串。from BeautifulSoup import BeautifulSoup soup = BeautifulSoup("Hello") soup.contents[0]#u'Hello' soup.originalEncoding#'ascii'
from BeautifulSoup import BeautifulSoup soup = BeautifulSoup("xe3x81x93xe3x82x8cxe3x81xaf") soup.contents[0]#u'u3053u308cu306f' soup.originalEncoding#'utf-8' str(soup)#'xe3x81x93xe3x82x8cxe3x81xaf' #Note: this bit uses EUC-JP, so it only works if you have cjkcodecs#installed, or are running Python 2.4. soup.__str__('euc-jp')#'xa4xb3xa4xecxa4xcf'
UnicodeDammit
的类去来检测文档的编码,并将其转换为Unicode。如果你需要为其他文档(没有石油Beautiful Soup剖析过得文档)使用这转换,你也可以直接使用UnicodeDammit
。它是基于Universal Feed Parser开发的。
如果你使用Python2.4之前的版本,请下载和安装cjkcodecs
以及iconvcodec
是python支持更多的编码,特别是CJK编码。要想更好地自动检测,你也要安装chardet
Beautiful Soup 会按顺序尝试不同的编码将你的文档转换为Unicode:
- 可以通过
fromEncoding
参数传递编码类型给soup的构造器 - 通过文档本身找到编码类型:例如XML的声明或者HTML文档
http-equiv
的META标签。如果Beautiful Soup在文档中发现编码类型,它试着使用找到的类型转换文档。但是,如果你明显的指定一个编码类型,并且成功使用了编码:这时它会忽略任何它在文档中发现的编码类型。 - 通过嗅探文件开头的一下数据,判断编码。如果编码类型可以被检测到,它将是这些中的一个:UTF-*编码,EBCDIC或者ASCII。
- 通过
chardet
库,嗅探编码,如果你安装了这个库。 - UTF-8
- Windows-1252
cjkcodecs
的情况下才工作。):
from BeautifulSoup import BeautifulSoup euc_jp = 'xa4xb3xa4xecxa4xcf' soup = BeautifulSoup(euc_jp) soup.originalEncoding#'windows-1252' str(soup)#'xc2xa4xc2xb3xc2xa4xc3xacxc2xa4xc3x8f' # Wrong!
fromEncoding
参数指定编码,它可以正确的剖析文档,并可以将文档转换为UTF-8或者转回EUC-JP。
soup = BeautifulSoup(euc_jp, fromEncoding="euc-jp") soup.originalEncoding#'windows-1252' str(soup)#'xe3x81x93xe3x82x8cxe3x81xaf' # Right! soup.__str__(self, 'euc-jp') == euc_jp#True
BeautifulSoup
) 或者XML entitis(BeautifulStoneSoup
)。
但是,你可以指定参数smartQuotesTo=None
到soup构造器:这时 smart quotes会被正确的转换为Unicode。你也可以指定smartQuotesTo
为"xml"或"html" 去改变BeautifulSoup
和BeautifulStoneSoup
的默认操作。
from BeautifulSoup import BeautifulSoup, BeautifulStoneSoup text = "Deploy the x91SMART QUOTESx92!" str(BeautifulSoup(text))#'Deploy the ‘SMART QUOTES’!' str(BeautifulStoneSoup(text))#'Deploy the ‘SMART QUOTES’!' str(BeautifulSoup(text, smartQuotesTo="xml"))#'Deploy the ‘SMART QUOTES’!' BeautifulSoup(text, smartQuotesTo=None).contents[0]#u'Deploy the u2018SMART QUOTESu2019!'