Python之BeautifulSoup

本文介绍BeautifulSoup库的基本使用方法,包括安装、文档解析、标签搜索等核心功能。

1. Beautiful Soup的简介

    BeautifulSoup是python的一个库,可以很方便地提取出HTML或XML标签中的内容。

2. Beautiful Soup 安装

    BeautifulSoup3 目前已经停止开发,现在使用比较多的是beautifulSoup4,导入时我们需要用 import bs4 。
    据说 BS4 对 Python3 的支持不够好,不过我还没啥感觉。

Windows
如果你电脑里同时安装了python2和python3,那么请这样做:
python2:pip install beautifulsoup4
python3:pip3 install beautifulsoup4
如果pip3 install beautifulsoup4不好使的话,可以使用:py -3 - m install beautifulsoup4
安装了Py3.5出现’HTMLParseError’的同学可以看这个方法:

https://www.zhihu.com/question/37949586

    出现No module named bs4的看这个方法:

http://sandy.epwing.com/archives/12.html

Linux
sudo apt-get install python-bs4
Mac
sudo easy_install pip
pip install beautifulsoup4
 

3.官方文档

http://beautifulsoup.readthedocs.io/zh_CN/latest/

4.使用方法

↓↓↓↓↓↓↓↓↓↓↓↓↓以下代码部分引用官方文档,只进行了一些补充说明

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><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>
"""

html_doc是一个字符串
首先导入bs4

from bs4 import BeautifulSoup

然后

soup = BeautifulSoup(html_doc, 'html.parser')
print(soup.prettify())

也可以用本地 HTML 文件来创建对象

soup = BeautifulSoup(open('index.html'))

返回标签

print soup.title
#<title>The Dormouse's story</title>
print soup.p
#<p class="title" name="dromouse"><b>The Dormouse's story</b></p>

BeautifulSoup 对象包含了一个值为 "[document]” 的特殊属性 .name

soup.name
#u'[document]'

find_all()可以得到所有的标签,或是通过名字得到比一个tag更多的内容:

soup.find_all('a')
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

.contents 和 .children
tag的 .contents 属性可以将tag的子节点以列表的方式输出:

head_tag = soup.head
head_tag
# <head><title>The Dormouse's story</title></head>

head_tag.contents
[<title>The Dormouse's story</title>]

title_tag = head_tag.contents[0]
title_tag
# <title>The Dormouse's story</title>
title_tag.contents
# [u'The Dormouse's story']

通过tag的 .children 生成器,可以对tag的子节点进行循环,可以用来显示文本内容:

for child in title_tag.children:
    print(child)
# The Dormouse's story

.descendants
.contents 和 .children 属性仅包含tag的直接子节点.例如,标签只有一个直接子节点

head_tag.contents
# [<title>The Dormouse's story</title>]

但是标签也包含一个子节点:字符串 “The Dormouse’s story”,这种情况下字符串 “The Dormouse’s story”也属于标签的子孙节点. .descendants 属性可以对所有tag的子孙节点进行递归循环:

for child in head_tag.descendants:
    print(child)
    # <title>The Dormouse's story</title>
    # The Dormouse's story

↑↑↑↑↑↑↑↑↑可以发现是依次输出的

.string
如果tag只有一个 NavigableString 类型子节点,那么这个tag可以使用 .string 得到子节点:

title_tag.string
# u'The Dormouse's story'

如果一个tag仅有一个子节点,那么这个tag也可以使用 .string 方法,输出结果与当前唯一子节点的 .string 结果相同:

head_tag.contents
# [<title>The Dormouse's story</title>]

head_tag.string
# u'The Dormouse's story'

如果tag包含了多个子节点,tag就无法确定 .string 方法应该调用哪个子节点的内容, .string 的输出结果是 None :

print(soup.html.string)
# None

↑↑↑↑↑↑↑↑↑.string可以返回标签内部的文本信息,但是只能返回一个确定的信息,多了就不行了

.strings 和 stripped_strings
如果tag中包含多个字符串 ,可以使用 .strings 来循环获取:

for string in soup.strings:
    print(repr(string))

输出的字符串中可能包含了很多空格或空行,使用 .stripped_strings 可以去除多余空白内容:

for string in soup.stripped_strings:
    print(repr(string))

.parent
通过 .parent 属性来获取某个元素的父节点.在例子“爱丽丝”的文档中,标签是标签的父节点:

title_tag.parent
# <head><title>The Dormouse's story</title></head

.parents
通过元素的 .parents 属性可以递归得到元素的所有父辈节点

link = soup.a
link
# <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
for parent in link.parents:
    if parent is None:
        print(parent)
    else:
        print(parent.name)
# p
# body
# html
# [document]
# None

find_all()
在find_all() 方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容:

soup.find_all('b')
# [<b>The Dormouse's story</b>]

传入正则表达式作为参数,BeautifulSoup会通过正则表达式的 match() 来匹配内容.下面例子中找出所有以b开头的标签,这表示<body><b>标签都应该被找到:

import re
for tag in soup.find_all(re.compile("^b")):
    print(tag.name)
# body
# b

如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有<a>标签和<b>标签:

soup.find_all(["a", "b"])
# [<b>The Dormouse's story</b>,
#  <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>

方法
如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 ,如果这个方法返回 True 表示当前元素匹配并且被找到,如果不是则反回 False

下面方法校验了当前元素,如果包含 class 属性却不包含 id 属性,那么将返回 True:

def has_class_but_no_id(tag):
    return tag.has_attr('class') and not tag.has_attr('id')

将这个方法作为参数传入 find_all() 方法,将得到所有

标签:

soup.find_all(has_class_but_no_id)
# [<p class="title"><b>The Dormouse's story</b></p>,
#  <p class="story">Once upon a time there were...</p>,
#  <p class="story">...</p>]

find()
find()与 find_all() 唯一的区别是find_all() 方法的返回结果是值包含一个元素的列表,而 find() 方法直接返回结果.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值