bs4的用法之遍历文档树以及查找文档树
"""
#### bs4的使用
from bs4 import BeautifulSoup
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"id="id_p"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
soup = BeautifulSoup(html_doc, 'lxml')
# 美化格式
# print(soup.prettify())
##### 遍历文档树
#1、用法(通过.来查找,只能找到第一个)
# tag对象
head = soup.head
title = head.title
print(head)
print(title)
p = soup.p # 只能找到第一个
print(p)
# 2、获取标签的名称
# tag对象
p = soup.p
from bs4.element import Tag
print(type(p))
print(p.name)
# 3、获取标签的属性
p = soup.p
# 方式一 通过[]来获取
# 获取class属性,可以有多个,拿到列表
print(p['class'])
print(p['id'])
# 方式二:通过attrs来获取
print(p.attrs['class'])
print(p.attrs.get('id'))
# 4、获取标签的内容
p = soup.p
print(p.text) # 所有层级的都拿出来拼到一起
print(p.string) # 只有一层,可以取出
print(p.strings) # 把每一层都取出来,做成一个生成器
# 5、嵌套选择
title = soup.head.title
print(title)
# 6、子节点,子孙节点
p1 = soup.p.children # 迭代器
p2 = soup.p.contents # 列表
print(list(p1))
print(p2)
# 7、父节点,祖先节点
p1 = soup.p.parent # 直接父节点
p2 = soup.p.parents # 祖先节点
print(p1)
print(list(p2)) # 它的祖先,包括它父亲的祖先都拿出来
# 8、兄弟节点
print(soup.a.next_sibling) # 下一个兄弟
print(soup.a.previous_sibling) # 上一个兄弟
print(list(soup.a.next_siblings)) #下面的兄弟们=>生成器对象
print(soup.a.previous_siblings) #上面的兄弟们=>生成器对象
##### 查找文档树(find, find_all) 速度比遍历文档树慢
# 可以两个配合着使用 eg:(soup.p.find())
# 五种过滤器:字符串,正则表达式,列表,true,方法
# 这五种下面以find为例
# 1、字符串查找,引号内是字符串
p = soup.find(name='p')
p = soup.find(name='body')
print(p)
# 查找类名是title的所有标签,由于class是关键字,得用class_
ret = soup.find_all(class_='title')
# 查找属性为http://example.com/elsie的标签
ret = soup.find_all(href='http://example.com/elsie')
# 查找id为xx的标签
ret = soup.find_all(id='id_p')
print(ret)
# 2、正则表达式
import re
reg = re.compile('^b') #编译一个正则表达式,返回一个对象
ret = soup.find_all(name=reg)
# # 找id以id开头的标签
reg = re.compile('^id')
ret = soup.find_all(id=reg)
print(ret)
# 3、列表
ret = soup.find_all(name=['body', 'b'])
ret = soup.find_all(id=['id_p', 'link1'])
ret = soup.find_all(class_=['id_p', 'link1'])
# and 关系
ret = soup.find_all(class_='title', name='p')
print(ret)
# 4、True
# 所有有名字的标签
ret = soup.find_all(name=True)
# 所有有id的标签
ret = soup.find_all(id=True)
# 所有有href属性的
ret = soup.find_all(href=True)
print(ret)
# 5 方法
def has_class_but_no_id(tag):
return tag.has_attr('class') and not tag.has_attr('id')
print(soup.find_all(has_class_but_no_id))
# 6、其他使用
ret = soup.find_all(attrs={'class': 'title'})
ret = soup.find_all(attrs={'id': 'id_p', 'class': 'title'})
print(ret)
# 7、拿到标签,取属性,取text
ret = soup.find_all(attrs={'id': 'id_p', 'class': 'title'})
print(ret[0].text)
# 8、limit(限制条数)
soup.find() # 其实就是find_all 然后limit 为1
ret = soup.find_all(name=True, limit=2)
print(len(ret))
# 9、recursive
# recursive = False # 只找儿子,不递归查找,只找第一层
ret = soup.body.find_all(name='p', recursive=False)
print(ret)
"""