python爬虫:使用BeautifulSoup进行查找
网页中有用的信息通常存在于网页中的文本或各种不同标签的属性值,为了获得这些网页信息,有必要有一些查找方法可以获取这些文本值或标签属性。而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是例程要用到的参考网页
- <html>
- <body>
- <div class="ecopyramid">
- <ul id="producers">
- <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>
- </ul>
- <ul id="primaryconsumers">
- <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>
- <ul>
- <ul id="secondaryconsumers">
- <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>
- </ul>
- <ul id="tertiaryconsumers">
- <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>
- </ul>
- </body>
- </html>
以上代码是一个生态金字塔的简单展示,为了找到其中的第一生产者,第一消费者或第二消费者,我们可以使用Beautiful Soup的查找方法。一般来说,为了找到BeautifulSoup对象内任何第一个标签入口,我们可以使用find()方法。
找到第一生产者
可以明显看到,生产者在第一个<ul>标签里,因为生产者是在整个HTML文档中第一个<ul>标签中出现,所以可以简单的使用find()方法找到第一生产者。下图HTML树代表了第一个生产者所在位置。
然后在ecologicalpyramid.py中写入下面一段代码,使用ecologicalpyramid.html文件创建BeautifulSoup对象。
- from bs4 import BeautifulSoup
- with open("ecologicalpyramid.html","r") as ecological_pyramid:
- soup = BeautifulSoup(ecological_pyramid)
- producer_entries = soup.find("ul")
- print(producer_entries.li.div.string)
输出得到:plants
find()说明
find()函数如下:
find(name,attrs,recursive,text,**wargs)
这些参数相当于过滤器一样可以进行筛选处理。
不同的参数过滤可以应用到以下情况:
- 查找标签,基于name参数
- 查找文本,基于text参数
- 基于正则表达式的查找
- 查找标签的属性,基于attrs参数
- 基于函数的查找
通过标签查找
我们可以传递任何标签的名字来查找到它第一次出现的地方。找到后,find函数返回一个BeautifulSoup的标签对象。
- from bs4 import BeautifulSoup
- with open("ecologicalpyramid.html", "r") as ecological_pyramid:
- soup = BeautifulSoup(ecological_pyramid,"html")
- producer_entries = soup.find("ul")
- print(type(producer_entries))
输出的得到 <class 'bs4.element.Tag'>
通过文本查找
直接字符串的话,查找的是标签。如果想要查找文本的话,则需要用到text参数。如下所示:
- from bs4 import BeautifulSoup
- with open("ecologicalpyramid.html", "r") as ecological_pyramid:
- soup = BeautifulSoup(ecological_pyramid,"html")
- plants_string = soup.find(text="plants")
- print(plants_string)
输出:plants
通过正则表达式查找
有以下HTML代码:
- <br/>
- <div>The below HTML has the information that has email ids.</div>
- abc@example.com
- <div>xyz@example.com</div>
- <span>foo@example.com</span>
如果想找出第一个邮箱地址,但是由于第一个邮箱地址没有标签包含,所以通过其他方式很难找到。但是我们可以把邮箱地址进行正则表达式处理,这样就容易多了。
参考如下代码:
- import re
- from bs4 import BeautifulSoup
- email_id_example = """<br/>
- <div>The below HTML has the information that has email ids.</div>
- abc@example.com
- <div>xyz@example.com</div>
- <span>foo@example.com</span>
- """
- soup = BeautifulSoup(email_id_example)
- emailid_regexp = re.compile("\w+@\w+\.\w+")
- first_email_id = soup.find(text=emailid_regexp)
- print(first_email_id)
输出:abc@example.com
通过标签属性进行查找
观看例程HTML代码,其中第一消费者在ul标签里面且id属性为priaryconsumers.
因为第一消费者出现的ul不是文档中第一个ul,所以通过前面查找标签的办法就行不通了。现在通过标签属性进行查找,参考代码如下:
- from bs4 import BeautifulSoup
- with open("ecologicalpyramid.html", "r") as ecological_pyramid:
- soup = BeautifulSoup(ecological_pyramid,"html")
- primary_consumer = soup.find(id="primaryconsumers")
- print(primary_consumer.li.div.string)
输出:deer
通过标签属性查找的方式适用于大多数标签属性,包括id,style,title,但是有一组标签属性例外。
- Custom attrbutes
- Class
基于定制属性的查找
- customattr = ""'<p data-custom="custom">custom attribute
- example</p>"""
- customsoup = BeautifulSoup(customattr,'lxml')
- customSoup.find(data-custom="custom")
那么则会报错。原因是在Python中变量不能呢含有-这个字符,而我们传递的data-custom有-这个字符。
- css_class = soup.find(attrs={'class':'primaryconsumerlist'})
- print(css_class)
还有另一个办法。BeautifulSoup有一个特别的关键字参数class_。示例:
- css_class = soup.find(class_ = "primaryconsumers" )
方法2:
- def is_secondary_consumers(tag):
- return tag.has_attr('id') and tag.get('id') ==
- 'secondaryconsumers'
- secondary_consumer = soup.find(is_secondary_consumers)
- print(secondary_consumer.li.div.string)
输出:fox
把方法进行组合后进行查找
使用find_all查找
查找所有三级消费者
- all_tertiaryconsumers =
- soup.find_all(class_="tertiaryconsumerslist")
其all_tertiaryconsumers的类型是列表。
- for tertiaryconsumer in all_tertiaryconsumers:
- print(tertiaryconsumer.div.string)
输出:
理解用于find_all()的参数
- email_ids = soup.find_all(text=emailid_regexp)
- print(email_ids)
输出:[u'abc@example.com',u'xyz@example.com',u'foo@example.com']
- email_ids_limited = soup.find_all(text=emailid_regexp,limit=2)
- print(email_ids_limited)
- all_texts = soup.find_all(text=True)
- print(all_texts)
输出:
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']
- all_texts_in_list = soup.find_all(text=["plants","algae"])
- print(all_texts_in_list)
输出:
- [u'plants', u'algae']
这个同样适用于查找标签,标签属性,定制属性和CSS类。如:
- div_li_tags = soup.find_all(["div","li"])
find()和find_all()都会查找一个对象所有后辈们,不过我们可以控制它通过recursive参数。如果recursive=False,那么超找只会找到该对象的最近后代。
通过标签之间的关系进行查找
查找父标签
- primaryconsumers = soup.find_all(class_="primaryconsumerlist")
- primaryconsumer = primaryconsumers[0]
- parent_ul = primaryconsumer.find_parents('ul')
- print(parent_ul)
一个简单的找到一个标签的父标签的方法就是使用find_parent()却不带任何参数。
- producers= soup.find(id='producers')
- next_siblings = producers.find_next_siblings()
- print(next_siblings)
查找下一个
- first_div = soup.div
- all_li_tags = first_div.find_all_next("li")
输出“:
<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>]