Bootstrap

网页数据解析与爬取----Beautiful Soup

网页数据解析与爬取----Beautiful Soup

Beautiful Soup 使用

1、Beautiful Soup简介

1、解析工具Beautiful Soup,其借助网页的结构和属性等特性来解析网页
2、Beautiful Soup是Python的一个HTML或XML的解析库,可方便地从网页中提取数据,提供一些简单的、Python式的函数来处理导航、搜索、修改分析树等功能
3、Beautiful Soup自动将输入文档转换为Unicode编码,将输出文档转换为utf-8编码
4、Beautiful Soup可省去很多繁琐的提取工作,提高解析网页效率

2、解析器

Beautiful Soup在解析时是依赖解析器的,除了支持Python标准库中的HTML解析器,还支持一些第三方解析器
Beautiful Soup常用解析器
在这里插入图片描述

推荐使用LXML解析器,它有解析HTML和XML的功能,速度快、容错能力强

3、准备工作

1、安装Beautiful Soup库

pip install beautifulsoup4

2、基本使用

html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
# 调用prettify方法,这个方法可以把要解析的字符串以标准的缩进格式输出
print(soup.prettify())
# 调用soup.title.string,输出html中title节点的文本内容
print(soup.title.string)

4、节点选择器

说明:直接调用节点的名称即可选择节点,然后调用string属性就可得到节点内的文本,这个方法只会选择到第一个匹配的节点,后面的其他节点都会忽略

html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.title)
print(type(soup.title))
print(soup.title.string)
print(soup.head)
print(soup.p)

5、提取信息

1、获取名称

说明:利用name属性获取节点的名称

print(soup.title.name)  --> title
2、获取属性

一个节点可能有多个属性,例如id和class等,选择这个节点元素后,可调用attrs获取其所有属性

# 调用attrs属性的返回结果是字典形式,包括与哦所有选择节点的所有属性和属性值
print(soup.p.attrs)
print(soup.p.attrs['name'])
# 简写
print(soup.p['name'])
print(soup.p['class'])
3、获取内容

利用string属性获取节点元素包括的文本内容

# 只获取第一个节点
print(soup.p.string)
4、嵌套选择
html = """
<html><head><title>The Dormouse's story</title></head>
<body>
"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.head.title)
print(type(soup.head.title))
print(soup.head.title.string)

6、关联选择

在做选择过程中,有时不能一步就选到想要的节点,需要先选中某一个节点,再以它为基准选子节点、父节点、兄弟节点等

1、子节点和子孙节点

选取节点之后,如果想要获取它的直接子节点,可调用contents属性

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.p.contents) # 返回结果是列表类型

也可调用children属性得到相应的结果

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
# 返回结果是生成器类型
print(soup.p.children)
for i,child in enumerate(soup.p.children):
    print(i, child) 

如果要得到所有的子孙节点,可调用descendants属性

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
# 返回结果是生成器类型
print(soup.p.descendaants)
for i,child in enumerate(soup.p.descendaants):
    print(i, child) 
2、父节点和祖先节点

如果要获取某个节点元素的父节点,可调用parent属性

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
# 返回结果是生成器类型
print(soup.a.parent)

如果想获取所有祖先节点,可调用parents属性

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
# 返回结果是生成器类型
print(soup.a.parents)
3、兄弟节点

获取兄弟节点

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
# 获取节点的下一个兄弟节点
print('Next Sibling', soup.a.next_sibling)
# 获取节点的上一个兄弟节点
print('Prev Sibling', soup.a.previous_sibling)
# 返回后面的所有兄弟节点
print('Next Siblings', list(enumerate(soup.a.next_siblings)))
# 返回前面的所有兄弟节点
print('Prev Siblings', list(enumerate(soup.a.previous_siblings)))

7、方法选择器

1、find_all

find_all,查询所有符合条件的元素,可给它传入一些属性或文本来得到符合条件的元素

find_all(name, attrs, recursive, text, **kwargs)
2、name

根据name属性查询元素

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.find_all(name='ul'))
print(type(soup.find_all(name='ul')[0]))
3、attrs

根据属性进行查询

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.find_all(attrs={'id':'list1'}))
4、text

text参数可以用来匹配节点的文本,其传入形式可以是字符串,也可是正则表达式对象

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.find_all(text=re.compile('link')))
5、find

find方法也可查询符合条件的元素,只不过find方法返回的是单个元素,即匹配第一个元素,而find_all会返回由所有匹配的元素组成的列表

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.find(name='ul'))
print(soup.find(text=re.compile('link')))

说明:
find_parents和find_parent:前者返回所有祖先节点,后者返回直接父节点
find_next_siblings 和 find_next_sibling:前者返回后面的所有兄弟节点,后者返回后面第一个兄弟节点
find_previous_siblings 和 find_previous_sibling:前者返回前面所有兄弟节点,后者返回前面第一个兄弟节点
find_all_next 和 find_next:前者返回节点后面所有符合条件的节点,后者返回后面第一个符合条件的节点
find_all_previous 和 find_previous:前者返回节点前面所有符合条件的节点,后者返回前面第一个符合条件的节点

8、CSS选择器

只需调用select方法,传入相应的CSS选择器即可

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.select('.panel .panel-heading'))
print(soup.select('ul li'))
1、嵌套选择
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
for ul in soup.select('ul'):
    print(ul.select('li'))
2、获取属性

使用attrs获取属性

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
for ul in soup.select('ul'):
    print(ul['id'])
    print(ul.attrs['id'])
3、获取文本

使用string属性获取文本

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
for li in soup.select('li):
    print('Get text:', li.get_text())
    print('String:', li.string)
;