版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、参考文档: HYPERLINK /software/BeautifulSoup/bs4/doc.zh/ Beautiful Soup 4.2.0中文文档BeautifulSoup是一个可以从html或者xml文件中提取数据的一个Python第三方库。我们可以在编写爬 虫项目的时候,使用BeautifulSoup来帮助我们解析html文件。 o 1、安装 BeautifulSoup-2、安装解析器 3、使用 BeautifulSoup3.1、编码问题3.2、BeautifulSoup的对象3.2.1、Tag对象.parents & .parent.contents & .children.str
2、ing.strings & .stripped_stringsget_text()3.2.2、NavigableString对象3.3、搜寻目标Tag3.3.1、过滤器字符串-正则表达式-列表-函数方法3.3.2、find_all()name参数attr s参数keyword 参数按css搜索string 参数limit参数recursive 参数find_all()方法的简写3.3.3、find()find()方法的使用find()方法的简写-3.3.4、其他搜索APIfind_parents() & find_parent()find_next_siblings() & find_next
3、_sibling()find_previous_siblings() & find_previous_sibling()find_all_next() & find_next()find_all_previous() & find_previous() 3.3.5、css选择器 4、如何提高效率解析部分文档(SoupStrainer)文档解析错误代码诊断(diagnose)-5、使用更高版本应注意的内容1、安装 BeautifulSoupPython的第三方库一般都可以使用pip来进行安装,使用pip进行安装的方法是:pip install beautifulsoup4也可以使用easy_in
4、stall来进行安装:easy_install beautifulsoup4BeautifulSoup的发布协议允许将bs4的代码打包在项目中,可以无须安装便可以使用。2、安装解析器BeautifulSoup支持Python标准库中的HTML解析器(html.parser无需安装),也支持一些第三方的解 析器,其中一个是lxml,也支持html5lib, html5lib是纯Python实现,解析方式与浏览器相同解析器的安装和BeautifulSoup的安装类似:easy_install lxmlpip install lxmleasy_install html5libpip install
5、html5lib各个解析器的对比如下:解析器使用方法优势劣势Python标准库BeautifulSoup (markup, Python的内置标 Python 2.7.3 orhtml.parser )3.2.2)前的版本执彳亍速度适中中文档容错能力文档容错能力强差Ixml HTML解析器BeautifulSoup(markup,速度快需要安装C语言库Ixml )文档容错能力强IxmlXML解析器BeautifulSoup (markup,灘快需要安装C语言库唯一支持XML的解析器Beau tiful Sou p (tna rkup,*xmr)htrnl5libBeau tiful Sou p
6、 (ma rkup,*html51ib*)-最好的容错性-速度慢以浏览器的方式不依赖外部扩展解析文档生成HTML5格式的文档推荐使用Ixml作为解析器,因为效率更高。在Python2.7.3之前的版本和Python3中322之前的版本, 必须安装I xml或htm I5I ib,因为那些Python版本的标准库中内置的HTML解析方法不够稳定。3、使用 BeautifulSoup使用BeautifulSoup的方法和其他Python库的方法类似from bs4 import BeautifulSoup 我们可以将我们采集到的网页内容传入BeautifulSoup的构造方法,就能得到一个文档的对
7、象,也可 以传入一段字符串或一个文件句柄。soup = BeautifulSoup(html,html.parser)soup = BeautifulSoup(open(html.html,),html.parser)soup = BeautifulSoup(,data,,html.parser,)我们需要注意到,文档在传入构造方法之后均被转换成Unicode,并且HTML的实例都被转换成 Unicode 编码。3.1、编码问题任何HTML或XML文档都有自己的编码方式,比如ASCII或UTF-8,但是使用BeautifulSoup解析后, 文档都被转换成了 Unicode。Beautiful
8、Soup用了编码自动检测子库来识别当前文档编码并转换成Unicode编码。BeautifulSoup对 象的.original_encoding属性记录了自动识别编码的结果。也可以通过from_encoding属性来指定编码 格式。soup = BeautifulSoup(html,from_encoding=,utf-8,)我们在编写爬虫的时候,一般都会遇到中文编码的显示问题,一般我们是将request s的返回,传入 BeautifulSoup的构造方法中,有时候会出现中文乱码的情况,我们这里以百度官网 为例,看一下怎么解决编码问题。import requestsfrom bs4 impo
9、rt BeautifulSoupres = requests.get(,)print(res.encoding)soup = BeautifulSoup(res.text,,lxml,)print(soup)print(soup.original_encoding)当我们运行上面这些代码的时候,我们会发现我们输出的soup是乱码。我们查看requestes以及 BeautifulSoup的相关文档,发现request s会自动将从服务器端获取到的内容自动转换成unicode,而 BeauifulSoup也会将获取到内容自动转换成unicode。requests和BeautifulSoup会自行
10、猜测原文的编 码格式,大多数时候猜测出来的编码都是正确的,但也有猜错的情况,如果猜错了可以指定原文的编 码。所以我们认为是上面是由于编码格式猜测错误导致的中文乱码,我们查看res.encoding的输出结果 为ISO-8859-T,然后在网页中的charset属性指出网页是utf-8编码格式的,所以我们需要指定原文 的编码:res.encoding = ,utf-8,然后再传入BeautifulSoup中,我们输出的soup时中文显示就正常了。我们在通过BeautifulSoup输出文档时,不管输入文档是什么编码方式,输出编码均为utf-8编码。如 果我们不想使用utf-8格式输出文档,或者因
11、为有些字符乱码而需要使用其他编码格式的时候,那我 们只需要:soup.encode(,你想要的编码,)#orsoup.prettify(,你想要的编码,)#prettify()除了可以指定编码外,最主要功能是对beautifulsoup的k语法分析树重新排版ps:针对中文编码问题,我们也可以以bytes传递给BeautifulSoup,-般bs都能猜测到正确的编码。import reuqestsfrom bs4 import BeautifulSoupres = requests.get()soup = BeautifulSoup(res.content,lxml)print(soup.pre
12、ttify()输出中文正常显示。3.2、BeautifulSoup的对象BeautifulSoup将复杂HTML文档转换成一个树形结构,每个节点都是Python对象,所有对象可以归为 4种:Tag, NavigableString, BeautifulSoup, Comment。我们在编写爬虫代码的时候主要使用的是 Tag和NavigableString对象,所以着重介绍一下。我们使用bs的最重要的目的是解析html文档,从里 面提取出我们所需要的内容,当然bs还有很多其他非常好的功能。3.2.1、Tag对象Tag对象与XML或HTML原生文档中的tag相同,我们也可以认为是树形结构中的节点。
13、一个Tag可能 包含多个字符串或其它的Tag,这些都是这个Tag的子节点。Beautiful Soup提供了许多操作和遍历子 节点的属性.我们可以通过.tag_name的方法来获得子节点,但是这种方法只能获得第一个匹配到的节点。soup = BeautifulSoup(vb id=bold class=boldestExtremely bold) tag_b = soup.b type(tag_b)#每个tag都有自己的名字,可以通过.name来获取:tag_#b个tag可能有很多个属性,例如tag_b有一个“id”的属性,值为“blod”,有一个“class”的属性,值 为“boldest”
14、 , tag的属性的操作方法与字典相同。也可以通过使用.attrs的方式,获得所有的属 性。HTML4定义了一系列可以包含多个值的属性,在HTML5中移除了一些,却增加更多,最常见的多值 的属性是class (tag可以有多个CSS的class),还有一些属性rel, rev, accept-charset, headers, accesskey等等。在BeautifulSoup中多值属性的返回类型是list。tag_bclass#boldesttag_b.attrs#id: bold, class: boldest)css_soup = BeautifulSoup() css_soup.pc
15、lass#bodyt strikeout.parents & .parenttag对象的.parent属性,可以获取某个节点的父节点。例如,head标签是title标签的父节点, 我们可以这么获得。title_tag = soup.titletitle_tag#This is a storyv/titletitle_tag.parent#This is a storytag对象的.parents属性是递归返回当前tag对象的所有父辈节点。.contents & .childrentag的.contents属性可以将tag的子节点以列表的方式输出:soup = BeautifulSoup(Ext
16、remely bold123) soup.a.contents#Extremely bold, 123也可以通过tag的.children生成器,对tag的子节点进行循环:for child in soup.a.children:print(child)#Extremely bold#123.string如果tag只有一个NavigableString类型子节点,也就是只有一个字符串节点,没有其他tag,那么这 个tag可以使用.string得到子节点:soup.a.b.stringExtremely bold.strings & .stripped_strings如果tag中包含多个字符串,
17、可以使用.strings来循环获取:soup = BeautifulSoup( Extremely boldv/bxb class=boldestExtremely bold1n123)for string in soup.a.strings:print(string)#Extremely bold#Extremely boldl#123输出的字符串中可能包含了很多空格或空行,使用.stripped_strings可以去除多余空白内容:soup = BeautifulSoup(Extremely boldExtremely bold1n123)for string in soup.a.stri
18、pped_strings:print(string)#Extremely bold#Extremely boldl#123get_text()如果只想得到tag中包含的文本内容,那么可以调用get_text()方法,这个方法获取到tag中包含的所有 文字内容包括子孙tag中的内容,并将结果作为Unicode字符串返回:soup = BeautifulSoup(Extremely bold123) soupaget_text()soupa.b.get_text()#Extremely bold123#Extremely bold注意:Beautiful Soup中字符串节点不支持以上这些属性,因
19、为字符串没有子节点3.2.2、NavigableString对象字符串常被包含在tag内,Beautiful Soup用NavigableString类来包装tag中的字符串。一个 NavigableString字符串与Python中的U nicode字符串相同。tag中包含的字符串不能编辑,但是可以被替换成其它的字符串,用replace_with()方法:soup = BeautifulSoup(123,)soup.b.string.replace_with(replace,)soup.b#replace注:一个字符串不能包含其它内容(tag能够包含字符串或是其它tag),字符串不支持.co
20、ntents或 .string属性或find()方法。3.3、搜寻目标Tag在我们获得正确的网页返回内容之后,我们需要搜寻到正确的目标Tag来获得我们想要的内容。 Beautiful Soup定义了很多搜索方法,这里着重介绍2个:find()和find_all(),其它方法的参数和用法 类似。3.3.1、过滤器介绍find_all()方法前,先介绍一下过滤器的类型,这些过滤器贯穿整个搜索的API。过滤器可以被用 在tag的name中,节点的属性中,字符串中或他们的混合中。我们使用下面的html,作为我们解析的内容html =,123456321654 I Isoup = BeautifulSo
21、up(html)字符串最简单的过滤器是字符串,在搜索方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整 匹配的内容,下面的例子用于查找文档中所有的标签:soup.find_all(b)#123f 456v/b, 321f 654字符串过滤器的主要功能是筛选出=字符串的节点正则表达式如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的match()来匹配内容。下面例子 中找出所有以b开头的标签,这表示和标签都应该被找到:import refor tag in soup.find_all(pile(b):print()#body#b#b#b#b列表如果传
22、入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回。下面代码找到文档中所 有标签和标签:soup.find_all(a,b)#123456 , 123, 456, 321654, 321, 654函数方法如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数,如果这个方法返回 True表示当前元素匹配并且被找到,如果不是则反回False。下面方法校验了当前tag,如果包含class属性却不包含id属性,那么将返回True:def has_class_but_no_id(tag):return tag.has_attr(class) and not tag.h
23、as_attr(id)将这个方法作为参数传入find_all()方法,将得到所有满足条件的标签:soup.find_all(has_class_but_no_id)#456f 654v/b可以看到返回结果中,只有满足含有class属性,不含有id属性”的标签被返回。3.3.2、 find_all()find_all( name , attrs , recursive , text , *kwargs )find_all()方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件。下面有几个例子,根据 find_all()方法的参数,进行理解。name参数name参数在之前的介绍中有所提
24、及,类似字符串过滤器。name参数查找所有名字为name的tag, 字符串对象会被自动忽略掉。soup.find_all(title)茸获得为“title ”的标签attrs参数attrs参数是根据tag属性,对标签进行查找。soup.find_all(attrs=class:bl)#获得满足class=bU的所有标签soup.find_all(b,attrs=class:b1,id=bold1)#获得满足class=b1” id=%old1 的所有标签keyword 参数如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜 索,如果包含一个名字为id的参数
25、,Beautiful Soup会搜索每个tag的” id”属性。soup.find_all(id=link2)#搜寻所有满足id=link2 的标签如果传入href参数,Beautiful Soup会搜索每个tag的”href”属性:soup.find_all(href=pile(https:/)#搜寻所有href为https开头的标签搜索指定名字的属性时可以使用的参数值包括字符串,正则表达式,列表,True,参照过滤器的使用 方法。soup.find_all(id=True)茸搜索查找所有包含id属性的标签,无论id的值是什么可以使用多个指定名字的参数可以同时过滤tag的多个属性:soup.
26、find_all(href=pile(https:/),id=link,)#搜索查找所有id为link href为https开头的标签注意:有些tag属性不能在搜索中使用,例如html5中的data-*属性soup = BeautifulSoup(,foo!,)soup.find_all(data-foo = value)#SyntaxError: keyword cant be an expression但是可以通过使用find_all()方法中的attrs参数来获得data-*的属性内容soup.find_all(attrs=,data-foo,:value,)#foo!按css搜索按照c
27、ss类名搜索tag的功能非常实用,但标识css类名的关键字class在Python中是保留字,使用 class做参数会导致语法错误。从BeautifulSoup的4丄1版本开始,可以通过class_参数搜索有指定 css类名的tag。soup.find_all(,a,,class_=,test,)茸搜索出所有class属性为test的标签class_参数同样接受不同类型的过滤器,例如:字符串,正则表达式,函数方法以及True。使用方 法和上面在讲过滤器的时候的使用方法类似,我们可以自行验证。tag的class是多值属性,按照css类名搜索tag的时候,可以分别搜索tag中的每个类名。soup
28、= BeautifulSoup(,)soup.find_all(,p,,class_=,body,)#v/psoup.find_all(,p,,class_=,table,) #v/p 同时使用class_也可以进行对css类名的完全匹配: soup.find_all(p,class_=bGdy tabel) #p class=body注意:如果在使用完全匹配clas s值的时候,如果css类名的顺序与实际不符,则不会搜索到正确的结 果。string参数通过string参数可以搜索文档中的字符串内容,它同样接受不同类型的过滤器,string参数接受字符 串,正则表达式,列表和True,同样也接
29、受函数方法过滤。注意:如果只使用了string参数,返回结果列表中的元素只包含满足搜索条件的字符串,也可以说是 NavigableString对象,而不是tag对象,可以观察下面的这两个语句进行对比。soup.find_all(string = test)#testsoup.find_all(a,string=test)#testlimit参数find_all()方法返回的是全部的搜索结构,那么如果文档树很大的时候搜索所需要的时间也会非常 大,如果我们不需要全部的搜索结果,那么我们可以使用limit参数来限制返回结果的数量。例如如果文档中有5个满足搜索条件的tag,当我们使用limit参数的时
30、候就可以限制它的返回数量。soup.find_all(a,limilt=2)#只返回满足搜索条件的前两个recursive 参数在调用find_all()方法时,默认的是搜索当前tag下的所有子孙节点,查找符合我们要求的tag。如果 我们只想搜索当前tag的直接子节点,可以使用参数recursive = Falsehtml = Test Title!soup = BeautifulSoup(html,lxml)souphtmlfind_all(title)#The Dormouses storysouphtmlfind_all(title,recursive二False)#标签在标签下,但并不
31、是直接子节点,标签才是直接子节点。在允许查询 所有后代节点时BeautifulSoup能够查找到标签。但是使用了 recursive=False参数之后, 只能查找直接子节点,这样就查不到标签了。find_all()方法的简写find_all()方法是BeautifulSoup中最常用的搜索方法,所以BeautifulSoup的作者定义了他的简写方 法,BeautifulSoup对象和tag对象可以被当作一个方法来使用,这个方法的执行结果和调用这个对象 的find_all()方法的结果相同。soup.find_all(a)soup(a)上面的这两行代码的执行结果是一样的,同样下面的这两行代码的
32、执行结果也是一样的。soup.title.find_all(string=True)soup.title(string=True)3.3.3、 find()find( name , attrs , recursive , string , *kwargs)find()方法的使用find()方法的参数使用与find_all()的类似,这里不再重新阐述。find_all()方法将返回文档中所有符合条件的tag,当我们只想得到一个结果时,可以使用limit参数, 或者可以直接使用find()方法,例如下面的两行代码是等价的。soup.find_all(title,limit=1)soup.find(
33、title)上面两行代码唯一的区别就是,find_all()方法返回的是包含一个元素的列表,而find()方法是直接 返回的结果。如果没有找到满足搜索条件的tag对象,findl()返回的是一个空列表,find()找不到 目标返回的是None。find()方法的简写soup.head.title是调用find()方法的简写,这个简写的原理就是多次调用当前tag的find()方法,下 面这两句代码是具有相同效果的。soup.head.titlesoup.find(head).find(title)3.3.4、其他搜索APIfind()和find_all()方法是最常使用的搜索文档的方法,但是Be
34、autifulSoup还给我们提供了 10个可以 使用搜索功能的API,其中五个与find_all()方法的参数相同,另外五个与find()方法的参数类似,这 里不再做举例验证。find_parents() & find_parent()find_parents(name, attrs, recursive, string, *kwargs)find_parent(name, attrs, recursive, string, *kwargs)find()和find_all()方法是搜索当前节点的子孙节点,find_parent()和find_parents()则是用来搜索 当前节点的父辈节点
35、。同样两个方法的区别是,在参数缺省的时候,find_parent()只返回直接父亲 节点(1个),find_parents()迭代返回所有的父辈节点。find_next_siblings() & find_next_sibling()find_next_siblings(name, attrs, recursive, string, *kwargs)find_next_sibling(name, attrs, recursive, string, *kwargs)这两个方法通过.next_siblings属性对当前tag节点后面所有满足搜索条件的兄弟tag节点进行迭代, 两个方法的区别是fin
36、d_next_siblings()返回所有满足搜索条件的兄弟节点,find_next_sibling()只 返回满足搜索条件的第一个兄弟节点。find_previous_siblings() & find_previous_sibling()find_previous_siblings(name, attrs, recursive, string, *kwargs)find_previous_sibling(name, attrs, recursive, string, *kwargs)这两个方法是通过.previous_siblings属性对当前tag节点前面所有满足搜索条件的兄弟tag节点
37、进行迭 代,两个方法的区别是find_previous_siblings()返回所有满足搜索条件的兄弟节点, find_previous_sibling()只返回满足走索条件的第一个兄弟节点。find_all_next() & find_next()find_all_next(name, attrs, recursive, string, *kwargs)find_next(name, attrs, recursive, string, *kwargs)这2个方法通过.next_elements属性对当前节点之后的tag和字符串进行迭代,find_all_next()方法 返回所有符合条件的节
38、点,find_next()方法返回第一个符合条件的节点。find_all_previous() & find_previous()find_all_previous(name, attrs, recursive, string, *kwargs)find_previous(name, attrs, recursive, string, *kwargs)这2个方法通过.previous_elements属性对当前节点前面的tag和字符串进行迭代, find_all_previous()方法返回所有符合条件的节点,find_previous()方法返回第一个符合条件的节 点。3.3.5、css选择
39、器BeautifulSoup支持大部分的CSS选择器,在tag或者BeautifulSoup对象的.select。方法中传入字符 串,就可以使用css选择器的语法找到目标tag。熟练使用css的人,可以选择使用css选择器来进行搜索。css选择器的使用方法,可以自行查找官方文档的相关使用,本人由于掌握的不好,便不在这里班门 弄斧了。4、如何提高效率BeautifulSoup解析文档的速度不会比它所依赖的解析器的速度更快,如果对时间要求比较高,那我 们应该直接使用lxml作为BeautifulSoup所依赖的解析器,用lxml作解析器比用html5lib或者 python的内置解析器速度要快很多
40、。在安装c chardet后对文档解码的编码检测也会更快。此外一个更好提高速率的方法是,解析部分文档虽然不会节省多少解析时间,但是会节省很多内存, 并且搜索时也会变得更快。解析部分文档(SoupStrainer)如果仅仅是想查找文章中的a标签而对整个文档进行解析,实在是浪费内存和时间,最快的方法是 从一开始就将出了a标签之外的内容都忽略掉。SoupStrainer类可以定义文档的某段内容,这样 搜索文档时就不必解析整个文档,只会解析在SoupStrainer中定义过的文档。这样我们只需要构建 个SoupStrainer对象,并作为parse_only的参数传递个BeautifulSoup构造方
41、法即可。SoupStrainer 具有与典型搜索方法相同的参数,name, attrs, recursive, string, *kwargs,下面 举例说明三种SoupStrainer对象。from bs4 import SoupStraineronly_a_tags = SoupStrainer(a)only_tags_with_id_link2 = SoupStrainer(id=link2)def is_short_string(string):return len(string) vtitleThe Dormouses storyv/titlev/headThe Dormouses
42、storyv/bx/pOnce upon a time there were three little sisters; and their names wereElsie,Lacie andTillie;and they lived at the bottom of a well.v/pprint(BeautifulSoup(html_doc,lxml,parse_only=only_a_tags).prttify()#a class=sister href= HYPERLINK /elsie /elsie id=link1uElsie#Lacie#Tillie#print(Beautifu
43、lSoup(html_doc,lxml,parse_only=only_tags_with_id_link2).prettify()#Lacie#print(BeautifulSoup(html_doc,lxml,parse_only=only_short_strings).prettify()#Elsie#,#Lacie#and#Tillie此外还可以将S oupstrainer传入搜索方法中,可以实现同样的效果soup = BeautifulSoup(html_doc,) print(soup.find_all(only_short_strings)nf Elsie, fnf Lacie, andnf Tillie, nfn文档解析错误文档解析错误有两种,一种是崩溃,BeautifulSoup尝试解析一段文档结果却抛除了异常,通常是 HTMLParser.HTMLParseError。还有一种异常情况是Beaut
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 护理核心制度的持续改进
- 护理安全管理中的患者安全倡导
- 护理中的评估与计划
- 护理职称评审材料准备指南
- 部编版二年级语文下册《蜘蛛开店 第1课时》
- 护理服务流程优化与成本控制
- 护理安全中的用药安全
- 护理管理中的医疗健康管理
- 矿业企业资产勘探与管理工作面试技巧
- 基于脑机协同的智能车辆安全性能提升策略研究报告
- 桥牌协会内部管理制度
- 2026重庆市南岸区消防救援支队消防文员招录2人笔试备考试题及答案解析
- 肠道菌群移植培训课件
- 中国血脂管理指南理论知识考核试题及答案
- 公司核文化宣传手册
- YD-T 2664-2024 公用电信设施保护安全等级要求
- 医学影像学总论试题
- DB32-T 3310-2017船闸维护规程
- 新苏教版科学六年级下册全册教案(含反思)
- 世界现代化理论
- 内燃机车柴油机冷却水系统-交流传动内燃机车柴油机冷却水系统
评论
0/150
提交评论