python爬虫解析库BeautifulSoup

安装BeautifulSoup库

python -m pip install BeautifulSoup4

BeautifulSoup常用解析器,推荐lxml,确保安装了lxml库
这里写图片描述

from bs4 import BeautifulSoup
# 引用静觅的例子 https://cuiqingcai.com/5548.html
# 注意该html缺少"</body></html>"闭合
html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="story" name="dromouse">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>
"""
# 使用lxml解析器初始化BeautifulSoup,期间自动修正html代码,比如补全"</body></html>"
soup = BeautifulSoup(html, 'lxml')

# prettify()格式化html代码,比如代码缩进、换行等
print(soup.prettify())

print(soup.title.string) # 获取title节点里的文本内容
print(soup.title.name) # 获取title节点的名称,即:title
print(soup.p.attrs) # 获取第一个p节点的属性值,返回字典格式:{'class': ['story'], 'name': 'dromouse'}

# 获取第一个p节点的class属性值,由于class可能存在多个值,因此返回list:['story']
print(soup.p.attrs['class'])
print(soup.p['class'])

# 获取第一个p节点的name属性值:dromouse
print(soup.p.attrs['name']) 
print(soup.p['name'])

# 节点可嵌套,如<head>里面的<title>节点
print(soup.head.title.string)

#=============关联节点选择==================
# 获取节点下的直接子节点及文本,contents返回列表格式,children返回生成器
print(soup.p.contents)
print(soup.p.children)
for child in soup.p.contents: # for循环查看内容
    print(child,end='####')

# 获取节点下的所有子孙节点,返回一个生成器
print(soup.p.descendants)
for child in soup.p.descendants: # for循环查看内容
    print(child,end='####')

# 获取节点的直接父节点,第一个<a>节点的父节点是<p>,则返回该<p>节点的所有内容
print(soup.a.parent)
# 获取所有父节点,返回生成器
print(soup.a.parents)
# 获取节点的下个兄弟节点
print(soup.a.next_sibling)
# 获取节点的上个兄弟节点
print(soup.a.previous_sibling)
# 获取节点之后的所有兄弟节点,返回生成器
print(soup.a.next_siblings)
# 获取节点之前的所有兄弟节点,返回生成器
print(soup.a.previous_siblings)

# 选择关联节点也可提取信息,如获取文本、属性等内容
print(soup.title.parent.string)
print(list(soup.a.parents)[0])
print(list(soup.a.parents)[0].attrs['class'])
#如果返回结果是单个节点,那么可以直接调用string、attrs等属性获得其文本和属性;
#如果返回结果是多个节点的生成器,则可以转为列表后取出某个元素,然后再调用string、attrs等属性获取其对应节点的文本和属性

# =================方法选择器=================
html='''
<div class="panel">
    <div class="panel-heading">
        <h4>Hello</h4>
    </div>
    <div class="panel-body">
        <ul class="list" id="list-1" name="elements">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
            <li class="element">Jay</li>
        </ul>
        <ul class="list list-small" id="list-2">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
        </ul>
    </div>
</div>
'''
soup = BeautifulSoup(html, 'lxml')

# find_all(name , attrs , recursive , text , **kwargs)
# find()与find_all()基本相同,只是find()返回符合条件的第一个节点,find_all()返回所有符合条件的节点列表

# ---------------根据节点名称name查询--------------
# 获取所有ul节点,返回列表,每个元素就是一个ul节点
print(soup.find_all(name='ul'))
# 返回的每个ul节点,可以继续嵌套操作,如获取li节点,进而再获取li的文本
for ul in soup.find_all(name='ul'):
    print(ul.find_all(name='li'))
    for li in ul.find_all(name='li'):
        print(li.string)

# ---------------根据节点属性attrs查询--------------
# attrs参数接受的是字典类型,返回节点组成的列表
print(soup.find_all(attrs={'id': 'list-1'}))
print(soup.find_all(attrs={'name': 'elements'}))
# 常用属性如id、class等可以不用attrs,直接使用属性名传递,name不可用
# 注:class是关键字,需改写为class_
print(soup.find_all(id='list-1'))
print(soup.find_all(class_='element'))

# ---------------根据text查询--------------
# 传入的text参数可以是字符串,可以是正则表达式对象
import re
html='''
<div class="panel">
    <div class="panel-body">
        <a>Hello, this is a link</a>
        <a>Hello, this is a link, too</a>
    </div>
</div>
'''
soup = BeautifulSoup(html, 'lxml')
# 返回由符合条件的text组成的列表:['Hello, this is a link', 'Hello, this is a link, too']
print(soup.find_all(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():前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点。

# =================css选择器=================
# 调用select()方法,传入相应的CSS选择器
html='''
<div class="panel">
    <div class="panel-heading">
        <h4>Hello</h4>
    </div>
    <div class="panel-body">
        <ul class="list" id="list-1">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
            <li class="element">Jay</li>
        </ul>
        <ul class="list list-small" id="list-2">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
        </ul>
    </div>
</div>
'''
soup = BeautifulSoup(html, 'lxml')
print(soup.select('.panel .panel-heading'))
print(soup.select('ul li'))
print(soup.select('#list-2 .element'))
print(type(soup.select('ul')[0]))
# 嵌套
for ul in soup.select('ul'):
    print(ul.select('li'))
# 获取属性
for ul in soup.select('ul'):
    print(ul['id'])
    print(ul.attrs['id'])
# 获取文本,string属性或者get_text()方法均可
for li in soup.select('li'):
    print('Get Text:', li.get_text())
    print('String:', li.string)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值