bs4的用法之遍历文档树以及查找文档树

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)
"""
posted @ 2020-04-08 22:23  alen_zhan  阅读(285)  评论(0编辑  收藏  举报
返回顶部