Reference: http://blog.csdn.net/abclixu123/article/details/38502993

网页中有用的信息通常存在于网页中的文本或各种不同标签的属性值,为了获得这些网页信息,有必要有一些查找方法可以获取这些文本值或标签属性。而Beautiful Soup中内置了一些查找方式:

  • find()
  • find_all()
  • find_parent()
  • find_parents()
  • find_next_sibling()
  • find_next_siblings()
  • find_previous_sibling()
  • find_previous_siblings()
  • find_previous()
  • find_all_previous()
  • find_next()
  • find_all_next()

使用find()查找

以下这段HTML是例程要用到的参考网页

  1. <html>
  2. <body>
  3. <div class="ecopyramid">
  4. <ul id="producers">
  5. <li class="producerlist">
  6. <div class="name">plants</div>
  7. <div class="number">100000</div>
  8. </li>
  9. <li class="producerlist">
  10. <div class="name">algae</div>
  11. <div class="number">100000</div>
  12. </li>
  13. </ul>
  14. <ul id="primaryconsumers">
  15. <li class="primaryconsumerlist">
  16. <div class="name">deer</div>
  17. <div class="number">1000</div>
  18. </li>
  19. <li class="primaryconsumerlist">
  20. <div class="name">rabbit</div>
  21. <div class="number">2000</div>
  22. </li>
  23. <ul>
  24. <ul id="secondaryconsumers">
  25. <li class="secondaryconsumerlist">
  26. <div class="name">fox</div>
  27. <div class="number">100</div>
  28. </li>
  29. <li class="secondaryconsumerlist">
  30. <div class="name">bear</div>
  31. <div class="number">100</div>
  32. </li>
  33. </ul>
  34. <ul id="tertiaryconsumers">
  35. <li class="tertiaryconsumerlist">
  36. <div class="name">lion</div>
  37. <div class="number">80</div>
  38. </li>
  39. <li class="tertiaryconsumerlist">
  40. <div class="name">tiger</div>
  41. <div class="number">50</div>
  42. </li>
  43. </ul>
  44. </body>
  45. </html>

以上代码是一个生态金字塔的简单展示,为了找到其中的第一生产者,第一消费者或第二消费者,我们可以使用Beautiful Soup的查找方法。一般来说,为了找到BeautifulSoup对象内任何第一个标签入口,我们可以使用find()方法。

找到第一生产者

可以明显看到,生产者在第一个<ul>标签里,因为生产者是在整个HTML文档中第一个<ul>标签中出现,所以可以简单的使用find()方法找到第一生产者。下图HTML树代表了第一个生产者所在位置。

然后在ecologicalpyramid.py中写入下面一段代码,使用ecologicalpyramid.html文件创建BeautifulSoup对象。

  1. from bs4 import BeautifulSoup
  2. with open("ecologicalpyramid.html","r") as ecological_pyramid:
  3. soup = BeautifulSoup(ecological_pyramid)
  4. producer_entries = soup.find("ul")
  5. print(producer_entries.li.div.string)

输出得到:plants

find()说明

find()函数如下:

find(name,attrs,recursive,text,**wargs)

这些参数相当于过滤器一样可以进行筛选处理。

不同的参数过滤可以应用到以下情况:

  • 查找标签,基于name参数
  • 查找文本,基于text参数
  • 基于正则表达式的查找
  • 查找标签的属性,基于attrs参数
  • 基于函数的查找

 通过标签查找

我们可以传递任何标签的名字来查找到它第一次出现的地方。找到后,find函数返回一个BeautifulSoup的标签对象。

  1. from bs4 import BeautifulSoup
  2. with open("ecologicalpyramid.html", "r") as ecological_pyramid:
  3. soup = BeautifulSoup(ecological_pyramid,"html")
  4. producer_entries = soup.find("ul")
  5. print(type(producer_entries))

输出的得到 <class 'bs4.element.Tag'>

通过文本查找

直接字符串的话,查找的是标签。如果想要查找文本的话,则需要用到text参数。如下所示:

  1. from bs4 import BeautifulSoup
  2. with open("ecologicalpyramid.html", "r") as ecological_pyramid:
  3. soup = BeautifulSoup(ecological_pyramid,"html")
  4. plants_string = soup.find(text="plants")
  5. print(plants_string)

输出:plants

通过正则表达式查找

有以下HTML代码:

  1. <br/>
  2. <div>The below HTML has the information that has email ids.</div>
  3. abc@example.com
  4. <div>xyz@example.com</div>
  5. <span>foo@example.com</span>

如果想找出第一个邮箱地址,但是由于第一个邮箱地址没有标签包含,所以通过其他方式很难找到。但是我们可以把邮箱地址进行正则表达式处理,这样就容易多了。

参考如下代码:

  1. import re
  2. from bs4 import BeautifulSoup
  3. email_id_example = """<br/>
  4. <div>The below HTML has the information that has email ids.</div>
  5. abc@example.com
  6. <div>xyz@example.com</div>
  7. <span>foo@example.com</span>
  8. """
  9. soup = BeautifulSoup(email_id_example)
  10. emailid_regexp = re.compile("\w+@\w+\.\w+")
  11. first_email_id = soup.find(text=emailid_regexp)
  12. print(first_email_id)

输出:abc@example.com

通过标签属性进行查找

观看例程HTML代码,其中第一消费者在ul标签里面且id属性为priaryconsumers.

因为第一消费者出现的ul不是文档中第一个ul,所以通过前面查找标签的办法就行不通了。现在通过标签属性进行查找,参考代码如下:

  1. from bs4 import BeautifulSoup
  2. with open("ecologicalpyramid.html", "r") as ecological_pyramid:
  3. soup = BeautifulSoup(ecological_pyramid,"html")
  4. primary_consumer = soup.find(id="primaryconsumers")
  5. print(primary_consumer.li.div.string)

输出:deer

通过标签属性查找的方式适用于大多数标签属性,包括id,style,title,但是有一组标签属性例外。

  • Custom attrbutes
  • Class
此时,我们需要借助attrs参数来进行传递。

基于定制属性的查找

 
比如我们HTML5标签中的data-custom属性,如果我们这样
  1. customattr = ""'<p data-custom="custom">custom attribute
  2. example</p>"""
  3. customsoup = BeautifulSoup(customattr,'lxml')
  4. customSoup.find(data-custom="custom")

那么则会报错。原因是在Python中变量不能呢含有-这个字符,而我们传递的data-custom有-这个字符。

解决的办法是在attrs属性用字典进行传递参数。
  1. using_attrs = customsoup.find(attrs={'data-custom':'custom'})
  2. print(using_attrs)

基于CSS类的查找

 
因为class是Python的保留关键字,所以无法使用class这个关键字。所以解决办法类似上面。
  1. css_class = soup.find(attrs={'class':'primaryconsumerlist'})
  2. print(css_class)

还有另一个办法。BeautifulSoup有一个特别的关键字参数class_。示例:

方法1:
  1. css_class = soup.find(class_ = "primaryconsumers" )

方法2:

  1. css_class = soup.find(attrs={'class':'primaryconsumers'})

基于定义的函数进行查找

可以传递函数到find()来基于函数定义的条件进行查找。函数值必须返回true或者false。
例子:
  1. def is_secondary_consumers(tag):
  2. return tag.has_attr('id') and tag.get('id') ==
  3. 'secondaryconsumers'
  1. secondary_consumer = soup.find(is_secondary_consumers)
  2. print(secondary_consumer.li.div.string)

输出:fox

 

把方法进行组合后进行查找

 
可以用其中任何方法进行组合来进行查找,比如同时基于标签名和id号。
 

使用find_all查找

find()用来查找第一个匹配结果出现的地方,而find_all()正如名字所示,将会找到所有匹配结果出现的地方。应用到find()中的不同过滤参数同理可以用到find_all()中,实际上,过滤参数可以用于任何查找函数,如find_parents()或和find_siblings()。
 

查找所有三级消费者

  1. all_tertiaryconsumers =
  2. soup.find_all(class_="tertiaryconsumerslist")

其all_tertiaryconsumers的类型是列表。

所以我们对其列表进行迭代,循环输出三级消费者的名字。
  1. for tertiaryconsumer in all_tertiaryconsumers:
  2. print(tertiaryconsumer.div.string)

输出:

lion
tiger
 

理解用于find_all()的参数

 
相比find(),find_all()有个额外的参数limit,如下所示:
find_all(name,attrs,recursive,text,limit,**kwargs)
limit参数可以限制我们想要得到结果的数目。参照前面的邮件地址例子,我们可以得到所有右键地址通过:
  1. email_ids = soup.find_all(text=emailid_regexp)
  2. print(email_ids)

输出:[u'abc@example.com',u'xyz@example.com',u'foo@example.com']

 
当我们使用limit参数,效果如下:
  1. email_ids_limited = soup.find_all(text=emailid_regexp,limit=2)
  2. print(email_ids_limited)
 

限制得到两个结果,所以输出为:

[u'abc@example.com',u'xyz@example.com']
 
说白了,find()也就是当limit=1时的find_all()。
 
可以向find函数传递True或False参数,如果我们传递True给find_all(),则返回所有soup对象的标签。对于find()来说,则返回第一个标签。
举例查找文本,传递True将会返回所有文本。
  1. all_texts = soup.find_all(text=True)
  2. print(all_texts)

输出:

[u'\n', u'\n', u'\n', u'\n', u'\n', u'plants', u'\n', u'100000', 
u'\n', u'\n', u'\n', u'algae', u'\n', u'100000', u'\n', u'\n', 
u'\n', u'\n', u'\n', u'deer', u'\n', u'1000', u'\n', u'\n', 
u'\n', u'rabbit', u'\n', u'2000', u'\n', u'\n', u'\n', 
u'\n', u'\n', u'fox', u'\n', u'100', u'\n', u'\n', u'\n', 
u'bear', u'\n', u'100', u'\n', u'\n', u'\n', u'\n', 
u'\n', u'lion', u'\n', u'80', u'\n', u'\n', u'\n', 
u'tiger', u'\n', u'50', u'\n', u'\n', u'\n', u'\n', 
u'\n']

同样的,我们可以在传递text参数时传递一个字符串列表,那么find_all()会找到诶个在列表中定义过的字符串。
  1. all_texts_in_list = soup.find_all(text=["plants","algae"])
  2. print(all_texts_in_list)

输出:

  1. [u'plants', u'algae']

这个同样适用于查找标签,标签属性,定制属性和CSS类。如:

  1. div_li_tags = soup.find_all(["div","li"])

find()和find_all()都会查找一个对象所有后辈们,不过我们可以控制它通过recursive参数。如果recursive=False,那么超找只会找到该对象的最近后代。

 

通过标签之间的关系进行查找

我们可以通过find()和find_all()来查找到想要内容。但有时候,我们需要查看的与之内容相关先前的标签或者后面的标签来获取额外的信息。比如方法find_parents()和find_next_siblings()等等。一般的,在find()和find_all()方法后使用上述方法,因为find()和find_all()可以找到特殊的一个标签,然后我们可以通过这个特殊的标签找到其他的想要的与之有关系的标签。
 

查找父标签

通过find_parents()或find_parent()。它们之间的不同就类似于find()和find_all()的区别。find_parents()返回全部的相匹配的父标签,而find_paret()返回最近的一个父标签。适用于find()的方法同样也使用于这两个方法。
 
在前面的第一消费者例子中,我们可以找到离Primaryconsumer最近的ul父标签。
  1. primaryconsumers = soup.find_all(class_="primaryconsumerlist")
  2. primaryconsumer = primaryconsumers[0]
  3. parent_ul = primaryconsumer.find_parents('ul')
  4. print(parent_ul)

一个简单的找到一个标签的父标签的方法就是使用find_parent()却不带任何参数。

  1. immediateprimary_consumer_parent = primary_consumer.find_parent()

查找同胞

 
如果标签在同一个等级的话,我们可以说这些标签是同胞的关系,比如参照上面金字塔例子,所有ul标签就是同胞的关系。
 
上图ul标签下的producers,primaryconsumers,secondaryconsumers,teriaryconsumers就是同胞关系。
再看下面这个图:
 
div下的plants和algae不是同胞关系,但是plants和临近的number是同胞关系。
Beautiful Soup自带有查找同胞的方法。
比如find_next_siblings()和find_next_sibling()查找对象下面的同胞。举例:
  1. producers= soup.find(id='producers')
  2. next_siblings = producers.find_next_siblings()
  3. print(next_siblings)
 

将会输出与之临近的下面的所有同胞HTML代码。

 

查找下一个

对每一个标签来说,下一个元素可能会是定位字符串,标签对象或者其他BeautifulSoup对象。我们定义下一个元素为与当前元素最靠近的元素。这个不同于同胞定义。我们有方法可以找到我们想要标签的下一个其他元素对象。find_all_next()找到与当前元素靠近的所有对象。而find_next()找到离当前元素最接近的对象。

比如,找到在第一个div标签后的所有li标签
  1. first_div = soup.div
  2. all_li_tags = first_div.find_all_next("li")

输出“:

[<li class="producerlist">
<div class="name">plants</div>
<div class="number">100000</div>
</li>, <li class="producerlist">
<div class="name">algae</div>
<div class="number">100000</div>
</li>, <li class="primaryconsumerlist">
<div class="name">deer</div>
<div class="number">1000</div>
</li>, <li class="primaryconsumerlist">
<div class="name">rabbit</div>
<div class="number">2000</div>
</li>, <li class="secondaryconsumerlist">
<div class="name">fox</div>
<div class="number">100</div>
</li>, <li class="secondaryconsumerlist">
<div class="name">bear</div>
<div class="number">100</div>
</li>, <li class="tertiaryconsumerlist">
<div class="name">lion</div>
<div class="number">80</div>
</li>, <li class="tertiaryconsumerlist">
<div class="name">tiger</div>
<div class="number">50</div>
</li>]

Beautiful Soup 定位指南的更多相关文章

  1. Python Beautiful Soup学习之HTML标签补全功能

    Beautiful Soup是一个非常流行的Python模块.该模块可以解析网页,并提供定位内容的便捷接口. 使用下面两个命令安装: pip install beautifulsoup4 或者 sud ...

  2. Windows下安装BeautifulSoup4显示'You are trying to run the Python 2 version of Beautiful Soup under Python 3.(`python setup.py install`) or by running 2to3 (`2to3 -w bs4`).'

    按照网上教程,将cmd的目录定位到解压缩文件夹地址,然后 >>python setup.py install ( Window下不能直接解压tar.giz文件,可以使用7z解压软件提取解压 ...

  3. Beautiful Soup解析网页

    使用前步骤: 1.Beautiful Soup目前已经被移植到bs4,所以导入Beautiful Soup时先安装bs4库. 2.安装lxml库:如果不使用此库,就会使用Python默认的解析器,而l ...

  4. 爬虫---Beautiful Soup 初始

    我们在工作中,都会听说过爬虫,那么什么是爬虫呢? 什么是网络爬虫 爬虫基本原理 所谓网络爬虫就是一个自动化数据采集工具,你只要告诉它要采集哪些数据,丢给它一个 URL,就能自动地抓取数据了.其背后的基 ...

  5. 爬虫---Beautiful Soup 爬取图片

    上一篇简单的介绍Beautiful Soup 的基本用法,这一篇写下如何爬取网站上的图片,并保存下来 爬取图片 1.找到一个福利网站:http://www.xiaohuar.com/list-1-1. ...

  6. 【Python】使用Beautiful Soup等三种方式定制Jmeter测试脚本

    背景介绍 我们在做性能调优时,时常需要根据实际压测的情况,调整线程组的参数,比如循环次数,线程数,所有线程启动的时间等. 如果是在一台Linux机器上,就免不了在本机打开图形页面修改,然后最后传递到压 ...

  7. 使用Beautiful Soup编写一个爬虫 系列随笔汇总

    这几篇博文只是为了记录学习Beautiful Soup的过程,不仅方便自己以后查看,也许能帮到同样在学习这个技术的朋友.通过学习Beautiful Soup基础知识 完成了一个简单的爬虫服务:从all ...

  8. 网络爬虫: 从allitebooks.com抓取书籍信息并从amazon.com抓取价格(1): 基础知识Beautiful Soup

    开始学习网络数据挖掘方面的知识,首先从Beautiful Soup入手(Beautiful Soup是一个Python库,功能是从HTML和XML中解析数据),打算以三篇博文纪录学习Beautiful ...

  9. Python爬虫学习(11):Beautiful Soup的使用

    之前我们从网页中提取重要信息主要是通过自己编写正则表达式完成的,但是如果你觉得正则表达式很好写的话,那你估计不是地球人了,而且很容易出问题.下边要介绍的Beautiful Soup就可以帮你简化这些操 ...

随机推荐

  1. [转]修改hosts文件不起作用

    http://wayne173.iteye.com/blog/1876565 今天遇到个很奇怪的问题,在hosts文件里添加了一些域名指向后,发现根本没起作用,后来还发现个细节,就是hosts文件左下 ...

  2. EL表达式,保留小数点后两位

    你遇到过页面显示小数有9.987870488E9这个吗? 这是因为没有保留小数的原因 有时候用js保留小数很麻烦的时候,可以用EL表达式 <fmt:formatNumber type=" ...

  3. Android Studio的使用(五)--导入第三方Jar包

    本篇博文将介绍一下如何导入第三方Jar包. 1.首先将下载的Jar包直接Copy到libs目录下面,然后右击Jar文件,点击Add As Library后,在出现的弹出框点击确定即可. 2.打开bui ...

  4. php获取Linux网卡信息

    $data = exec("/sbin/ifconfig"); var_dump($data); 注意:有时候这种方式获取不到,应该是权限问题 在/var/rootP文件中添加ro ...

  5. java字符编码,字符转码

    编码:String->byte[]; str.getBytes(charsetName) 解码:byte[]->String; new String(byte[],charsetName) ...

  6. iOS数据持久化之数据库:SQLite和FMDB

    SQLite: SQLite是一款轻量级型的数据库,资源占用少.性能良好和零管理成本,具有零配置(无需安装和管理配置).独立(没有额外依赖).储存在单一磁盘文件中的一个完整的数据库.源码完全的开源.比 ...

  7. Android在一个APP中通过包名或类名启动另一个APP

    开发有时需要在一个应用中启动另一个应用,比如Launcher加载所有的已安装的程序的列表,当点击图标时可以启动另一个应用.一般我们知道了另一个应用的包名和MainActivity的名字之后便可以直接通 ...

  8. JAVA字符串编码转换常用类

    无论是对程序的本地化还是国际化,都会涉及到字符编码的转换的问题.尤其在web应用中常常需要处理中文字符,这时就需要进行字符串的编码转换,将字符串编码转换为GBK或者GB2312.一.关键技术点:    ...

  9. Myeclipse添加struts2支持后取消操作

    Myeclipse添加struts包后, 想重新加载的方法: 1. myelicpse,右键项目,选close project 2. 找到项目所在目录, 打开.classpath删除带有struts2 ...

  10. cron expr

    api docs说的很清楚,不需要去搜索, org.quartz 类 CronExpression java.lang.Object org.quartz.CronExpression 所有已实现的接 ...