这是我见过最牛逼,最全面的Beautiful Soup 4.2 教程!没有之一
<p style="color:rgb(34,34,34);font-family:'PingFang SC','Hiragino Sans GB','Microsoft YaHei','WenQuanYi Micro Hei','Helvetica Neue',Arial,sans-serif;background-color:rgb(255,255,255);"><span style="font-weight:700;">进群:125240963 ? ?即可获取数十套PDF! <p style="color:rgb(34,255);">Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间.<p style="color:rgb(34,255);">这篇文档介绍了BeautifulSoup4中所有主要特性,并且有小例子.让我来向你展示它适合做什么,如何工作,怎样使用,如何达到你想要的效果,和处理异常情况.<p style="color:rgb(34,255);">文档中出现的例子在Python2.7和Python3.2中的执行结果相同<p style="color:rgb(34,255);">你可能在寻找 Beautiful Soup3 的文档,Beautiful Soup 3 目前已经停止开发,我们推荐在现在的项目中使用Beautiful Soup 4,移植到BS4<p style="color:rgb(34,255);">寻求帮助<p style="color:rgb(34,255);">如果你有关于BeautifulSoup的问题,可以发送邮件到 讨论组 .如果你的问题包含了一段需要转换的HTML代码,那么确保你提的问题描述中附带这段HTML文档的 代码诊断 [1]<h1 style="font-size:24px;line-height:32px;color:rgb(34,255);">快速开始<p style="color:rgb(34,255);">下面的一段HTML代码将作为例子被多次用到.这是 爱丽丝梦游仙境的 的一段内容(以后内容中简称为 爱丽丝 的文档):<p style="color:rgb(34,255);">html_doc = """<p style="color:rgb(34,255);">Extremely bold<p style="color:rgb(34,255);"># KeyError: 'class'<p style="color:rgb(34,255);"><span style="font-weight:700;">print(tag.get('class'))<p style="color:rgb(34,255);"># None<p style="color:rgb(34,255);">多值属性<p style="color:rgb(34,255);">HTML 4定义了一系列可以包含多个值的属性.在HTML5中移除了一些,却增加更多.最常见的多值的属性是 class (一个tag可以有多个CSS的class). 还有一些属性 rel,rev,accept-charset,headers,accesskey . 在Beautiful Soup中多值属性的返回类型是list:<p style="color:rgb(34,255);">css_soup = BeautifulSoup('<p class="body strikeout">')<p style="color:rgb(34,255);">css_soup.p['class']<p style="color:rgb(34,255);"># ["body","strikeout"]<p style="color:rgb(34,255);">css_soup = BeautifulSoup('<p class="body">')<p style="color:rgb(34,255);"># ["body"]<p style="color:rgb(34,255);">如果某个属性看起来好像有多个值,但在任何版本的HTML定义中都没有被定义为多值属性,那么Beautiful Soup会将这个属性作为字符串返回<p style="color:rgb(34,255);">id_soup = BeautifulSoup('<p id="my id">')<p style="color:rgb(34,255);">id_soup.p['id']<p style="color:rgb(34,255);"># 'my id'<p style="color:rgb(34,255);">将tag转换成字符串时,多值属性会合并为一个值<p style="color:rgb(34,255);">rel_soup = BeautifulSoup(' Back to the <a rel="index">homepage ')<p style="color:rgb(34,255);">rel_soup.a['rel']<p style="color:rgb(34,255);"># ['index']<p style="color:rgb(34,255);">rel_soup.a['rel'] = ['index','contents']<p style="color:rgb(34,255);"><span style="font-weight:700;">print(rel_soup.p)<p style="color:rgb(34,255);">#Back to the <a rel="index contents">homepage <p style="color:rgb(34,255);">如果转换的文档是XML格式,那么tag中不包含多值属性<p style="color:rgb(34,255);">xml_soup = BeautifulSoup('<p class="body strikeout">','xml')<p style="color:rgb(34,255);">xml_soup.p['class']<p style="color:rgb(34,255);"># u'body strikeout'<p style="color:rgb(34,255);">可以遍历的字符串<p style="color:rgb(34,255);">字符串常被包含在tag内.Beautiful Soup用 NavigableString 类来包装tag中的字符串:<p style="color:rgb(34,255);">tag.string<p style="color:rgb(34,255);"># u'Extremely bold'<p style="color:rgb(34,255);">type(tag.string)<p style="color:rgb(34,255);"># <class 'bs4.element.NavigableString'><p style="color:rgb(34,255);">一个 NavigableString 字符串与Python中的Unicode字符串相同,并且还支持包含在 遍历文档树 和 搜索文档树 中的一些特性. 通过 unicode() 方法可以直接将 NavigableString 对象转换成Unicode字符串:<p style="color:rgb(34,255);">unicode_string = unicode(tag.string)<p style="color:rgb(34,255);">unicode_string<p style="color:rgb(34,255);">type(unicode_string)<p style="color:rgb(34,255);"># <type 'unicode'><p style="color:rgb(34,255);">tag中包含的字符串不能编辑,但是可以被替换成其它的字符串,用 replace_with() 方法:<p style="color:rgb(34,255);">tag.string.replace_with("No longer bold")<p style="color:rgb(34,255);">#No longer bold<p style="color:rgb(34,255);">NavigableString 对象支持 遍历文档树 和 搜索文档树 中定义的大部分属性,并非全部.尤其是,一个字符串不能包含其它内容(tag能够包含字符串或是其它tag),字符串不支持 .contents 或 .string 属性或 find() 方法.<p style="color:rgb(34,255);">如果想在Beautiful Soup之外使用 NavigableString 对象,需要调用 unicode() 方法,将该对象转换成普通的Unicode字符串,否则就算Beautiful Soup已方法已经执行结束,该对象的输出也会带有对象的引用地址.这样会浪费内存.<p style="color:rgb(34,255);">BeautifulSoup<p style="color:rgb(34,255);">BeautifulSoup 对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag 对象,它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法.<p style="color:rgb(34,255);">因为 BeautifulSoup 对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性.但有时查看它的 .name 属性是很方便的,所以 BeautifulSoup 对象包含了一个值为 “[document]” 的特殊属性 .name<p style="color:rgb(34,255);">soup.name<p style="color:rgb(34,255);"># u'[document]'<p style="color:rgb(34,255);">注释及特殊字符串<p style="color:rgb(34,255);">Tag,BeautifulSoup 几乎覆盖了html和xml中的所有内容,但是还有一些特殊对象.容易让人担心的内容是文档的注释部分:<p style="color:rgb(34,255);">markup = ""<p style="color:rgb(34,255);">soup = BeautifulSoup(markup)<p style="color:rgb(34,255);">comment = soup.b.string<p style="color:rgb(34,255);">type(comment)<p style="color:rgb(34,255);"># <class 'bs4.element.Comment'><p style="color:rgb(34,255);">Comment 对象是一个特殊类型的 NavigableString 对象:<p style="color:rgb(34,255);">comment<p style="color:rgb(34,255);"># u'Hey,buddy. Want to buy a used parser'<p style="color:rgb(34,255);">但是当它出现在HTML文档中时,Comment 对象会使用特殊的格式输出:<p style="color:rgb(34,255);"><span style="font-weight:700;">print(soup.b.prettify())<p style="color:rgb(34,255);"># <p style="color:rgb(34,255);">Beautiful Soup中定义的其它类型都可能会出现在XML的文档中: CData,ProcessingInstruction,Declaration,Doctype .与 Comment 对象类似,这些类都是 NavigableString 的子类,只是添加了一些额外的方法的字符串独享.下面是用CDATA来替代注释的例子:<p style="color:rgb(34,255);"><span style="font-weight:700;">from?<span style="font-weight:700;">bs4?<span style="font-weight:700;">import?CData<p style="color:rgb(34,255);">cdata = CData("A CDATA block")<p style="color:rgb(34,255);">comment.replace_with(cdata)<p style="color:rgb(34,255);"># <![CDATA[A CDATA block]]><p style="color:rgb(34,255);"># <h1 style="font-size:24px;line-height:32px;color:rgb(34,255);">遍历文档树<p style="color:rgb(34,255);">还拿”爱丽丝梦游仙境”的文档来做例子:<p style="color:rgb(34,255);">通过这段例子来演示怎样从文档的一段内容找到另一段内容<p style="color:rgb(34,255);">子节点<p style="color:rgb(34,255);">一个Tag可能包含多个字符串或其它的Tag,这些都是这个Tag的子节点.Beautiful Soup提供了许多操作和遍历子节点的属性.<p style="color:rgb(34,255);">注意: Beautiful Soup中字符串节点不支持这些属性,因为字符串没有子节点<p style="color:rgb(34,255);">tag的名字<p style="color:rgb(34,255);">操作文档树最简单的方法就是告诉它你想获取的tag的name.如果想获取 标签,只要用 soup.head :<p style="color:rgb(34,255);">soup.head<p style="color:rgb(34,255);"># 标签”,等等.Beautiful Soup提供了重现解析器初始化过程的方法. <p style="color:rgb(34,255);">.next_element 和 .previous_element<p style="color:rgb(34,255);">.next_element 属性指向解析过程中下一个被解析的对象(字符串或tag),结果可能与 .next_sibling 相同,但通常是不一样的.<p style="color:rgb(34,255);">这是“爱丽丝”文档中最后一个标签,它的 .next_sibling 结果是一个字符串,因为当前的解析过程 [2] 因为当前的解析过程因为遇到了标签而中断了:<p style="color:rgb(34,255);">last_a_tag = soup.find("a",id="link3")<p style="color:rgb(34,255);">last_a_tag<p style="color:rgb(34,255);">last_a_tag.next_sibling<p style="color:rgb(34,255);"># '; and they lived at the bottom of a well.'<p style="color:rgb(34,255);">但这个标签的 .next_element 属性结果是在标签被解析之后的解析内容,不是标签后的句子部分,应该是字符串”Tillie”:<p style="color:rgb(34,255);">last_a_tag.next_element<p style="color:rgb(34,255);">这是因为在原始文档中,字符串“Tillie” 在分号前出现,解析器先进入标签,然后是字符串“Tillie”,然后关闭标签,然后是分号和剩余部分.分号与标签在同一层级,但是字符串“Tillie”会被先解析.<p style="color:rgb(34,255);">.previous_element 属性刚好与 .next_element 相反,它指向当前被解析的对象的前一个解析对象:<p style="color:rgb(34,255);">last_a_tag.previous_element<p style="color:rgb(34,255);">last_a_tag.previous_element.next_element<p style="color:rgb(34,255);">.next_elements 和 .previous_elements<p style="color:rgb(34,255);">通过 .next_elements 和 .previous_elements 的迭代器就可以向前或向后访问文档的解析内容,就好像文档正在被解析一样:<p style="color:rgb(34,255);"><span style="font-weight:700;">for?element?<span style="font-weight:700;">in?last_a_tag.next_elements:<p style="color:rgb(34,255);"><span style="font-weight:700;">print(repr(element))<p style="color:rgb(34,255);"># <p class="story">...<p style="color:rgb(34,255);"># None<h1 style="font-size:24px;line-height:32px;color:rgb(34,255);">搜索文档树<p style="color:rgb(34,255);">Beautiful Soup定义了很多搜索方法,这里着重介绍2个: find() 和 find_all() .其它方法的参数和用法类似,请读者举一反三.<p style="color:rgb(34,255);">再以“爱丽丝”文档作为例子:<p style="color:rgb(34,255);">使用 find_all() 类似的方法可以查找到想要查找的文档内容<p style="color:rgb(34,255);">过滤器<p style="color:rgb(34,255);">介绍 find_all() 方法前,先介绍一下过滤器的类型 [3],这些过滤器贯穿整个搜索的API.过滤器可以被用在tag的name中,节点的属性中,字符串中或他们的混合中.<p style="color:rgb(34,255);">字符串<p style="color:rgb(34,255);">最简单的过滤器是字符串.在搜索方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容,下面的例子用于查找文档中所有的标签:<p style="color:rgb(34,255);">soup.find_all('b')<p style="color:rgb(34,255);"># [The Dormouse's story]<p style="color:rgb(34,255);">如果传入字节码参数,Beautiful Soup会当作UTF-8编码,可以传入一段Unicode 编码来避免Beautiful Soup解析编码出错<p style="color:rgb(34,255);">正则表达式<p style="color:rgb(34,255);">如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容.下面例子中找出所有以b开头的标签,这表示和标签都应该被找到:<p style="color:rgb(34,255);"><span style="font-weight:700;">import?<span style="font-weight:700;">re<p style="color:rgb(34,255);"><span style="font-weight:700;">for?tag?<span style="font-weight:700;">in?soup.find_all(re.compile("^b")):<p style="color:rgb(34,255);"><span style="font-weight:700;">print(tag.name)<p style="color:rgb(34,255);"># b<p style="color:rgb(34,255);">下面代码找出所有名字中包含”t”的标签:<p style="color:rgb(34,255);"><span style="font-weight:700;">for?tag?<span style="font-weight:700;">in?soup.find_all(re.compile("t")):<p style="color:rgb(34,255);"># title<p style="color:rgb(34,255);">列表<p style="color:rgb(34,255);">如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有标签和标签:<p style="color:rgb(34,255);">soup.find_all(["a","b"])<p style="color:rgb(34,255);"># [The Dormouse's story,255);"># <a class="sister" href="http://example.com/elsie" id="link1">Elsie,255);">True<p style="color:rgb(34,255);">True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点<p style="color:rgb(34,255);"><span style="font-weight:700;">for?tag?<span style="font-weight:700;">in?soup.find_all(True):<p style="color:rgb(34,255);"># head<p style="color:rgb(34,255);"># a<p style="color:rgb(34,255);">方法<p style="color:rgb(34,255);">如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 [4],如果这个方法返回 True 表示当前元素匹配并且被找到,如果不是则反回 False<p style="color:rgb(34,255);">下面方法校验了当前元素,如果包含 class 属性却不包含 id 属性,那么将返回 True:<p style="color:rgb(34,255);"><span style="font-weight:700;">def?has_class_but_no_id(tag):<p style="color:rgb(34,255);"><span style="font-weight:700;">return?tag.has_attr('class')?<span style="font-weight:700;">and?<span style="font-weight:700;">not?tag.has_attr('id')<p style="color:rgb(34,255);">将这个方法作为参数传入 find_all() 方法,将得到所有标签: <p style="color:rgb(34,255);">soup.find_all(has_class_but_no_id)<p style="color:rgb(34,255);"># [<p class="title">The Dormouse's story,255);"># <p class="story">Once upon a time there were...,255);"># <p class="story">...]<p style="color:rgb(34,255);">返回结果中只有标签没有标签,因为标签还定义了”id”,没有返回和 ,因为和中没有定义”class”属性.<p style="color:rgb(34,255);">下面代码找到所有被文字包含的节点内容:<p style="color:rgb(34,255);"><span style="font-weight:700;">from?<span style="font-weight:700;">bs4?<span style="font-weight:700;">import?NavigableString<p style="color:rgb(34,255);"><span style="font-weight:700;">def?surrounded_by_strings(tag):<p style="color:rgb(34,255);"><span style="font-weight:700;">return?(isinstance(tag.next_element,NavigableString)<p style="color:rgb(34,255);"><span style="font-weight:700;">and?isinstance(tag.previous_element,NavigableString))<p style="color:rgb(34,255);"><span style="font-weight:700;">for?tag?<span style="font-weight:700;">in?soup.find_all(surrounded_by_strings):<p style="color:rgb(34,255);"><span style="font-weight:700;">print?tag.name<p style="color:rgb(34,255);">现在来了解一下搜索方法的细节<p style="color:rgb(34,255);">find_all()<p style="color:rgb(34,255);">find_all( name,attrs,recursive,text,*kwargs )<p style="color:rgb(34,255);">find_all() 方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件.这里有几个例子:<p style="color:rgb(34,255);">soup.find_all("title")<p style="color:rgb(34,255);">soup.find_all("p","title")<p style="color:rgb(34,255);"># [<p class="title">The Dormouse's story]<p style="color:rgb(34,255);">soup.find_all("a")<p style="color:rgb(34,255);">soup.find_all(id="link2")<p style="color:rgb(34,255);"># [<a class="sister" href="http://example.com/lacie" id="link2">Lacie]<p style="color:rgb(34,255);">soup.find(text=re.compile("sisters"))<p style="color:rgb(34,255);">有几个方法很相似,还有几个方法是新的,参数中的 text 和 id 是什么含义? 为什么 find_all("p","title") 返回的是CSS Class为”title”的标签? 我们来仔细看一下 find_all() 的参数 <p style="color:rgb(34,255);">name 参数<p style="color:rgb(34,255);">name 参数可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉.<p style="color:rgb(34,255);">简单的用法如下:<p style="color:rgb(34,255);">重申: 搜索 name 参数的值可以使任一类型的 过滤器,字符窜,正则表达式,列表,方法或是 True .<p style="color:rgb(34,255);">keyword 参数<p style="color:rgb(34,255);">如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性.<p style="color:rgb(34,255);">soup.find_all(id='link2')<p style="color:rgb(34,255);">如果传入 href 参数,Beautiful Soup会搜索每个tag的”href”属性:<p style="color:rgb(34,255);">soup.find_all(href=re.compile("elsie"))<p style="color:rgb(34,255);"># [<a class="sister" href="http://example.com/elsie" id="link1">Elsie]<p style="color:rgb(34,255);">搜索指定名字的属性时可以使用的参数值包括 字符串,True .<p style="color:rgb(34,255);">下面的例子在文档树中查找所有包含 id 属性的tag,无论 id 的值是什么:<p style="color:rgb(34,255);">soup.find_all(id=True)<p style="color:rgb(34,255);">使用多个指定名字的参数可以同时过滤tag的多个属性:<p style="color:rgb(34,255);">soup.find_all(href=re.compile("elsie"),id='link1')<p style="color:rgb(34,255);"># [<a class="sister" href="http://example.com/elsie" id="link1">three]<p style="color:rgb(34,255);">有些tag属性在搜索不能使用,比如HTML5中的 data- 属性:<p style="color:rgb(34,255);">data_soup = BeautifulSoup('<div data-foo="value">foo!')<p style="color:rgb(34,255);">data_soup.find_all(data-foo="value")<p style="color:rgb(34,255);"># SyntaxError: keyword can't be an expression<p style="color:rgb(34,255);">但是可以通过 find_all() 方法的 attrs 参数定义一个字典参数来搜索包含特殊属性的tag:<p style="color:rgb(34,255);">data_soup.findall(attrs={"data-foo": "value"})<p style="color:rgb(34,255);"># [<div data-foo="value">foo!]<p style="color:rgb(34,255);">按CSS搜索<p style="color:rgb(34,255);">按照CSS类名搜索tag的功能非常实用,但标识CSS类名的关键字 class 在Python中是保留字,使用 class 做参数会导致语法错误.从Beautiful Soup的4.1.1版本开始,可以通过 class 参数搜索有指定CSS类名的tag:<p style="color:rgb(34,255);">soup.findall("a",class="sister")<p style="color:rgb(34,255);">class_ 参数同样接受不同类型的 过滤器,字符串,方法或 True :<p style="color:rgb(34,255);">soup.findall(class=re.compile("itl"))<p style="color:rgb(34,255);"><span style="font-weight:700;">def?has_six_characters(css_class):<p style="color:rgb(34,255);"><span style="font-weight:700;">return?css_class?<span style="font-weight:700;">is?<span style="font-weight:700;">not?None?<span style="font-weight:700;">and?len(css_class) == 6<p style="color:rgb(34,255);">soup.findall(class=has_six_characters)<p style="color:rgb(34,255);">tag的 class 属性是 多值属性 .按照CSS类名搜索tag时,可以分别搜索tag中的每个CSS类名:<p style="color:rgb(34,255);">css_soup.findall("p",class="strikeout")<p style="color:rgb(34,255);"># [<p class="body strikeout">]<p style="color:rgb(34,class="body")<p style="color:rgb(34,255);">搜索 class 属性时也可以通过CSS值完全匹配:<p style="color:rgb(34,class="body strikeout")<p style="color:rgb(34,255);">完全匹配 class 的值时,如果CSS类名的顺序与实际不符,将搜索不到结果:<p style="color:rgb(34,attrs={"class": "sister"})<p style="color:rgb(34,255);">text 参数<p style="color:rgb(34,255);">通过 text 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样,text 参数接受 字符串,True . 看例子:<p style="color:rgb(34,255);">soup.find_all(text="Elsie")<p style="color:rgb(34,255);"># [u'Elsie']<p style="color:rgb(34,255);">soup.find_all(text=["Tillie","Elsie","Lacie"])<p style="color:rgb(34,255);"># [u'Elsie',u'Lacie',u'Tillie']<p style="color:rgb(34,255);">soup.find_all(text=re.compile("Dormouse"))<p style="color:rgb(34,255);">[u"The Dormouse's story",u"The Dormouse's story"]<p style="color:rgb(34,255);">def is_the_only_string_within_a_tag(s):<p style="color:rgb(34,255);">""Return True if this string is the only child of its parent tag.""<p style="color:rgb(34,255);">return (s == s.parent.string)<p style="color:rgb(34,255);">soup.find_all(text=is_the_only_string_within_a_tag)<p style="color:rgb(34,255);"># [u"The Dormouse's story",u"The Dormouse's story",u'Elsie',u'Tillie',u'...']<p style="color:rgb(34,255);">虽然 text 参数用于搜索字符串,还可以与其它参数混合使用来过滤tag.Beautiful Soup会找到 .string 方法与 text 参数值相符的tag.下面代码用来搜索内容里面包含“Elsie”的标签:<p style="color:rgb(34,text="Elsie")<p style="color:rgb(34,255);"># [<a href="http://example.com/elsie" class="sister" id="link1">Elsie]<p style="color:rgb(34,255);">limit 参数<p style="color:rgb(34,255);">find_all() 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢.如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量.效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果.<p style="color:rgb(34,255);">文档树中有3个tag符合搜索条件,但结果只返回了2个,因为我们限制了返回数量:<p style="color:rgb(34,limit=2)<p style="color:rgb(34,255);"># <a class="sister" href="http://example.com/lacie" id="link2">Lacie]<p style="color:rgb(34,255);">recursive 参数<p style="color:rgb(34,255);">调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False .<p style="color:rgb(34,255);">一段简单的文档:<p style="color:rgb(34,255);"><p style="color:rgb(34,255);"><p style="color:rgb(34,255);">标签,是目标叶子节点的间接父辈节点,所以也可以被找到.包含class值为”title”的 标签不是不是目标叶子节点的父辈节点,所以通过 find_parents() 方法搜索不到. <p style="color:rgb(34,255);">find_parent() 和 find_parents() 方法会让人联想到 .parent 和 .parents 属性.它们之间的联系非常紧密.搜索父辈节点的方法实际上就是对 .parents 属性的迭代搜索.<p style="color:rgb(34,255);">find_next_siblings() 合 find_next_sibling()<p style="color:rgb(34,255);">find_next_siblings( name,255);">find_next_sibling( name,255);">这2个方法通过 .next_siblings 属性对当tag的所有后面解析 [5] 的兄弟tag节点进行迭代,find_next_siblings() 方法返回所有符合条件的后面的兄弟节点,find_next_sibling() 只返回符合条件的后面的第一个tag节点.<p style="color:rgb(34,255);">first_link = soup.a<p style="color:rgb(34,255);">first_link<p style="color:rgb(34,255);">first_link.find_next_siblings("a")<p style="color:rgb(34,255);"># [<a class="sister" href="http://example.com/lacie" id="link2">Lacie,255);">first_story_paragraph = soup.find("p","story")<p style="color:rgb(34,255);">first_story_paragraph.find_next_sibling("p")<p style="color:rgb(34,255);">find_previous_siblings() 和 find_previous_sibling()<p style="color:rgb(34,255);">find_previous_siblings( name,255);">find_previous_sibling( name,255);">这2个方法通过 .previous_siblings 属性对当前tag的前面解析 [5] 的兄弟tag节点进行迭代,find_previous_siblings() 方法返回所有符合条件的前面的兄弟节点,find_previous_sibling() 方法返回第一个符合条件的前面的兄弟节点:<p style="color:rgb(34,255);">last_link = soup.find("a",255);">last_link<p style="color:rgb(34,255);">last_link.find_previous_siblings("a")<p style="color:rgb(34,255);"># <a class="sister" href="http://example.com/elsie" id="link1">Elsie]<p style="color:rgb(34,255);">first_story_paragraph.find_previous_sibling("p")<p style="color:rgb(34,255);">find_all_next() 和 find_next()<p style="color:rgb(34,255);">find_all_next( name,255);">find_next( name,255);">这2个方法通过 .next_elements 属性对当前tag的之后的 [5] tag和字符串进行迭代,find_all_next() 方法返回所有符合条件的节点,find_next() 方法返回第一个符合条件的节点:<p style="color:rgb(34,255);">first_link.find_all_next(text=True)<p style="color:rgb(34,u',',u' and ',255);"># u'; and they lived at the bottom of a well.',u' ',u'...',u' ']<p style="color:rgb(34,255);">first_link.find_next("p")<p style="color:rgb(34,255);">第一个例子中,字符串 “Elsie”也被显示出来,尽管它被包含在我们开始查找的标签的里面.第二个例子中,最后一个标签也被显示出来,尽管它与我们开始查找位置的标签不属于同一部分.例子中,搜索的重点是要匹配过滤器的条件,并且在文档中出现的顺序而不是开始查找的元素的位置. <p style="color:rgb(34,255);">find_all_previous() 和 find_previous()<p style="color:rgb(34,255);">find_all_previous( name,255);">find_previous( name,255);">这2个方法通过 .previous_elements 属性对当前节点前面 [5] 的tag和字符串进行迭代,find_all_previous() 方法返回所有符合条件的节点,find_previous() 方法返回第一个符合条件的节点.<p style="color:rgb(34,255);">first_link.find_all_previous("p")<p style="color:rgb(34,255);"># [<p class="story">Once upon a time there were three little sisters; ...,255);"># <p class="title">The Dormouse's story]<p style="color:rgb(34,255);">first_link.find_previous("title")<p style="color:rgb(34,255);">find_all_previous("p") 返回了文档中的第一段(class=”title”的那段),但还返回了第二段,标签包含了我们开始查找的标签.不要惊讶,这段代码的功能是查找所有出现在指定标签之前的 标签,因为这个 标签包含了开始的标签,所以 标签一定是在之前出现的. <p style="color:rgb(34,255);">CSS选择器<p style="color:rgb(34,255);">Beautiful Soup支持大部分的CSS选择器 [6],在 Tag 或 BeautifulSoup 对象的 .select() 方法中传入字符串参数,即可使用CSS选择器的语法找到tag:<p style="color:rgb(34,255);">soup.select("title")<p style="color:rgb(34,255);">soup.select("p nth-of-type(3)")<p style="color:rgb(34,255);"># [<p class="story">...]<p style="color:rgb(34,255);">通过tag标签逐层查找:<p style="color:rgb(34,255);">soup.select("body a")<p style="color:rgb(34,255);">soup.select("html head title")<p style="color:rgb(34,255);">找到某个tag标签下的直接子标签 [6] :<p style="color:rgb(34,255);">soup.select("head > title")<p style="color:rgb(34,255);">soup.select("p > a")<p style="color:rgb(34,255);">soup.select("p > a:nth-of-type(2)")<p style="color:rgb(34,255);">soup.select("p > #link1")<p style="color:rgb(34,255);">soup.select("body > a")<p style="color:rgb(34,255);">找到兄弟节点标签:<p style="color:rgb(34,255);">soup.select("#link1 ~ .sister")<p style="color:rgb(34,255);">soup.select("#link1 + .sister")<p style="color:rgb(34,255);">通过CSS的类名查找:<p style="color:rgb(34,255);">soup.select(".sister")<p style="color:rgb(34,255);">soup.select("[class~=sister]")<p style="color:rgb(34,255);">通过tag的id查找:<p style="color:rgb(34,255);">soup.select("#link1")<p style="color:rgb(34,255);">soup.select("a#link2")<p style="color:rgb(34,255);">通过是否存在某个属性来查找:<p style="color:rgb(34,255);">soup.select('a[href]')<p style="color:rgb(34,255);">通过属性的值来查找:<p style="color:rgb(34,255);">soup.select('a[href="http://example.com/elsie"]')<p style="color:rgb(34,255);">soup.select('a[href^="http://example.com/"]')<p style="color:rgb(34,255);">soup.select('a[href$="tillie"]')<p style="color:rgb(34,255);"># [<a class="sister" href="http://example.com/tillie" id="link3">Tillie]<p style="color:rgb(34,255);">soup.select('a[href*=".com/el"]')<p style="color:rgb(34,255);">通过语言设置来查找:<p style="color:rgb(34,255);">multilingual_markup = """<p style="color:rgb(34,255);"><p lang="en">Hello<p style="color:rgb(34,255);"><p lang="en-us">Howdy,y'all<p style="color:rgb(34,255);"><p lang="en-gb">Pip-pip,old fruit<p style="color:rgb(34,255);"><p lang="fr">Bonjour mes amis<p style="color:rgb(34,255);">multilingual_soup = BeautifulSoup(multilingual_markup)<p style="color:rgb(34,255);">multilingual_soup.select('p[lang|=en]')<p style="color:rgb(34,255);"># [<p lang="en">Hello,255);"># <p lang="en-us">Howdy,y'all,255);"># <p lang="en-gb">Pip-pip,old fruit]<p style="color:rgb(34,255);">对于熟悉CSS选择器语法的人来说这是个非常方便的方法.Beautiful Soup也支持CSS选择器API,如果你仅仅需要CSS选择器的功能,那么直接使用 lxml 也可以,而且速度更快,支持更多的CSS选择器语法,但Beautiful Soup整合了CSS选择器的语法和自身方便使用API.<h1 style="font-size:24px;line-height:32px;color:rgb(34,255);">修改文档树<p style="color:rgb(34,255);">Beautiful Soup的强项是文档树的搜索,但同时也可以方便的修改文档树<p style="color:rgb(34,255);">修改tag的名称和属性<p style="color:rgb(34,255);">在 Attributes 的章节中已经介绍过这个功能,但是再看一遍也无妨. 重命名一个tag,改变属性的值,添加或删除属性:<p style="color:rgb(34,255);">修改 .string<p style="color:rgb(34,255);">给tag的 .string 属性赋值,就相当于用当前的内容替代了原来的内容:<p style="color:rgb(34,255);">markup = '<a href="http://example.com/">I linked to example.com'<p style="color:rgb(34,255);">tag = soup.a<p style="color:rgb(34,255);">tag.string = "New link text."<p style="color:rgb(34,255);"># <a href="http://example.com/">New link text.<p style="color:rgb(34,255);">注意: 如果当前的tag包含了其它tag,那么给它的 .string 属性赋值会覆盖掉原有的所有内容包括子tag<p style="color:rgb(34,255);">append()<p style="color:rgb(34,255);">Tag.append() 方法想tag中添加内容,就好像Python的列表的 .append() 方法:<p style="color:rgb(34,255);">soup = BeautifulSoup("Foo")<p style="color:rgb(34,255);">soup.a.append("Bar")<p style="color:rgb(34,255);">soup<p style="color:rgb(34,255);"># FooBar<p style="color:rgb(34,255);">soup.a.contents<p style="color:rgb(34,255);"># [u'Foo',u'Bar']<p style="color:rgb(34,255);">BeautifulSoup.new_string() 和 .new_tag()<p style="color:rgb(34,255);">如果想添加一段文本内容到文档中也没问题,可以调用Python的 append() 方法或调用工厂方法 BeautifulSoup.new_string() :<p style="color:rgb(34,255);">soup = BeautifulSoup("")<p style="color:rgb(34,255);">tag.append("Hello")<p style="color:rgb(34,255);">new_string = soup.new_string(" there")<p style="color:rgb(34,255);">tag.append(new_string)<p style="color:rgb(34,255);"># Hello there.<p style="color:rgb(34,255);">tag.contents<p style="color:rgb(34,255);"># [u'Hello',u' there']<p style="color:rgb(34,255);">如果想要创建一段注释,或 NavigableString 的任何子类,将子类作为 new_string() 方法的第二个参数传入:<p style="color:rgb(34,255);"><span style="font-weight:700;">from?<span style="font-weight:700;">bs4?<span style="font-weight:700;">import?Comment<p style="color:rgb(34,255);">new_comment = soup.new_string("Nice to see you.",Comment)<p style="color:rgb(34,255);">tag.append(new_comment)<p style="color:rgb(34,255);"># Hello there<p style="color:rgb(34,u' there',u'Nice to see you.']<p style="color:rgb(34,255);"># 这是Beautiful Soup 4.2.1 中新增的方法<p style="color:rgb(34,255);">创建一个tag最好的方法是调用工厂方法 BeautifulSoup.new_tag() :<p style="color:rgb(34,255);">original_tag = soup.b<p style="color:rgb(34,255);">new_tag = soup.new_tag("a",href="http://www.example.com")<p style="color:rgb(34,255);">original_tag.append(new_tag)<p style="color:rgb(34,255);">original_tag<p style="color:rgb(34,255);"># <a href="http://www.example.com"><p style="color:rgb(34,255);">new_tag.string = "Link text."<p style="color:rgb(34,255);"># <a href="http://www.example.com">Link text.<p style="color:rgb(34,255);">第一个参数作为tag的name,是必填,其它参数选填<p style="color:rgb(34,255);">insert()<p style="color:rgb(34,255);">Tag.insert() 方法与 Tag.append() 方法类似,区别是不会把新元素添加到父节点 .contents 属性的最后,而是把元素插入到指定的位置.与Python列表总的 .insert() 方法的用法下同:<p style="color:rgb(34,255);">tag.insert(1,"but did not endorse ")<p style="color:rgb(34,255);"># <a href="http://example.com/">I linked to but did not endorse example.com<p style="color:rgb(34,255);"># [u'I linked to ',u'but did not endorse',example.com]<p style="color:rgb(34,255);">insert_before() 和 insert_after()<p style="color:rgb(34,255);">insert_before() 方法在当前tag或文本节点前插入内容:<p style="color:rgb(34,255);">soup = BeautifulSoup("stop")<p style="color:rgb(34,255);">tag = soup.new_tag("i")<p style="color:rgb(34,255);">tag.string = "Don't"<p style="color:rgb(34,255);">soup.b.string.insert_before(tag)<p style="color:rgb(34,255);">soup.b<p style="color:rgb(34,255);"># Don'tstop<p style="color:rgb(34,255);">insert_after() 方法在当前tag或文本节点后插入内容:<p style="color:rgb(34,255);">soup.b.i.insert_after(soup.new_string(" ever "))<p style="color:rgb(34,255);"># Don't ever stop<p style="color:rgb(34,255);">soup.b.contents<p style="color:rgb(34,255);"># [Don't,u' ever ',u'stop']<p style="color:rgb(34,255);">clear()<p style="color:rgb(34,255);">Tag.clear() 方法移除当前tag的内容:<p style="color:rgb(34,255);">tag.clear()<p style="color:rgb(34,255);"># <a href="http://example.com/"><p style="color:rgb(34,255);">extract()<p style="color:rgb(34,255);">PageElement.extract() 方法将当前tag移除文档树,并作为方法结果返回:<p style="color:rgb(34,255);">a_tag = soup.a<p style="color:rgb(34,255);">i_tag = soup.i.extract()<p style="color:rgb(34,255);">a_tag<p style="color:rgb(34,255);"># <a href="http://example.com/">I linked to<p style="color:rgb(34,255);">i_tag<p style="color:rgb(34,255);"># example.com<p style="color:rgb(34,255);"><span style="font-weight:700;">print(i_tag.parent)<p style="color:rgb(34,255);">None<p style="color:rgb(34,255);">这个方法实际上产生了2个文档树: 一个是用来解析原始文档的 BeautifulSoup 对象,另一个是被移除并且返回的tag.被移除并返回的tag可以继续调用 extract 方法:<p style="color:rgb(34,255);">my_string = i_tag.string.extract()<p style="color:rgb(34,255);">my_string<p style="color:rgb(34,255);"># u'example.com'<p style="color:rgb(34,255);"><span style="font-weight:700;">print(my_string.parent)<p style="color:rgb(34,255);"># <p style="color:rgb(34,255);">decompose()<p style="color:rgb(34,255);">Tag.decompose() 方法将当前节点移除文档树并完全销毁:<p style="color:rgb(34,255);">soup.i.decompose()<p style="color:rgb(34,255);">replace_with()<p style="color:rgb(34,255);">PageElement.replace_with() 方法移除文档树中的某段内容,并用新tag或文本节点替代它:<p style="color:rgb(34,255);">new_tag = soup.new_tag("b")<p style="color:rgb(34,255);">new_tag.string = "example.net"<p style="color:rgb(34,255);">a_tag.i.replace_with(new_tag)<p style="color:rgb(34,255);"># <a href="http://example.com/">I linked to example.net<p style="color:rgb(34,255);">replace_with() 方法返回被替代的tag或文本节点,可以用来浏览或添加到文档树其它地方<p style="color:rgb(34,255);">wrap()<p style="color:rgb(34,255);">PageElement.wrap() 方法可以对指定的tag元素进行包装 [8],并返回包装后的结果:<p style="color:rgb(34,255);">soup = BeautifulSoup("I wish I was bold. ")<p style="color:rgb(34,255);">soup.p.string.wrap(soup.new_tag("b"))<p style="color:rgb(34,255);"># I wish I was bold.<p style="color:rgb(34,255);">soup.p.wrap(soup.new_tag("div"))<p style="color:rgb(34,255);">#I wish I was bold. Sacr<span style="font-weight:700;">xc3xa9?bleu!"<p style="color:rgb(34,255);">soup.h1<p style="color:rgb(34,255);">#Sacré bleu!<p style="color:rgb(34,255);">soup.h1.string<p style="color:rgb(34,255);"># u'Sacrxe9 bleu!'<p style="color:rgb(34,255);">这不是魔术(但很神奇),Beautiful Soup用了 编码自动检测 子库来识别当前文档编码并转换成Unicode编码. BeautifulSoup 对象的 .original_encoding 属性记录了自动识别编码的结果:<p style="color:rgb(34,255);">soup.original_encoding<p style="color:rgb(34,255);">'utf-8'<p style="color:rgb(34,255);">编码自动检测 功能大部分时候都能猜对编码格式,但有时候也会出错.有时候即使猜测正确,也是在逐个字节的遍历整个文档后才猜对的,这样很慢.如果预先知道文档编码,可以设置编码参数来减少自动检查编码出错的概率并且提高文档解析速度.在创建 BeautifulSoup 对象的时候设置 from_encoding 参数.<p style="color:rgb(34,255);"><span style="font-weight:700;">私信小编007即可获取数十套PDF!(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |