爬虫系列:BeautifulSoup4解析
官网:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/
进阶
find模糊搜索
import requests,re
from bs4 import BeautifulSoup
'''
find()方法比较low 只存在网上祖传代码 个人不建议使用
推荐后面的CSS选择器用法
bs4官方文档-find模糊搜索:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/#id28
'''
html = requests.get('https://www.baidu.com')
html.encoding = 'utf-8'
soup = BeautifulSoup(html.text,'lxml')
'''
recursive参数:如果只想搜索Tag的直接子节点,可以使用参数recursive = False
find()---返回str
find_all()---返回list
'''
# print(soup.find(recursive=True))
# print(soup.find_all(recursive=True))
'''
name参数:
写法一:str类型,标签的名称,比如a,p,h1等
写法二:可迭代对象,比如:['a','p'] ('a','p')
写法三:正则表达式
find_all()---返回list
'''
# print(soup.find_all(name='a'))
# print(soup.find_all(name=['a','p']))
# print(soup.find_all(name=re.compile('^a')))
'''
limit参数:限制返回条数,比如:1,5,10
find_all()---返回list
'''
# print(soup.find_all(name='a',limit=2))
'''
attrs参数:根据指定属性搜索
find_all()---返回list
'''
# attrs = {
# 'class':'mnav'
# }
# print(soup.find_all(attrs=attrs))
'''
**keyward参数:任意参数映射
注意:如果搜索class要写成class_ 因为class是python关键字
find_all()---返回list
'''
# print(soup.find_all(class_='mnav'))
# print(soup.find_all(id='kw'))
'''
其他方法,官方都用详细介绍,这里就不演示了
find(name,attrs,recursive,text,**kwargs)
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选择器
from bs4 import BeautifulSoup
'''
select_one() 返回第一个节点 str类型
select() 返回list类型
bs4官方文档-CSS选择器:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/#id42
'''
HTML = '''
<!DOCTYPE html>
<html lang = "en">
<head>
<title>123</title>
<a id='one' href='https://example.com/demo1'>
<p class='test'>Test1</p>
<p class='test'>Test2</p>
</a>
<a id='two' href='https://example.com/demo2'>
<p class='test'>Test3</p>
<p class='test'>Test4</p>
</a>
<a id='three' href='https://example.com/demo3'>
<p class='test'>Test5</p>
<p class='test'>Test6</p>
</a>
<a class="h">
<p>干扰项标签</p>
</a>
<a class="h hh hhh hhhh">
<p>正确标签</p>
</a>
</head>
<body>
</body>
</html>
'''
soup = BeautifulSoup(HTML,'lxml')
'''
按照标签名搜索
'''
# print(soup.select_one('a'))
# print(soup.select('a'))
'''
获取该节点属性
'''
# print(soup.select_one('a')['href'])
'''
获取该节点的内容
'''
# print(soup.select_one('a').text)
'''
多个节点选择一个节点
'''
# print(soup.select('a')[0])
'''
按照某个属性搜索(用 [] 声明)
类似于正则表达式(支持 ^ $ *)
'''
# print(soup.select("a[href='https://example.com/demo1']"))
# print(soup.select("a[href^='https://example.com']"))
# print(soup.select("a[href$='demo1']"))
# print(soup.select("a[href*='demo']"))
soup.select('a[href="http://example.com/elsie"]')
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
soup.select('a[href^="http://example.com/"]')
# [<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>]
soup.select('a[href$="tillie"]')
# [<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
soup.select('a[href*=".com/el"]')
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
'''
按照id搜索(用 # 声明)
id存在唯一性,使用select_one()即可
'''
# print(soup.select_one('a#one'))
'''
按照class属性搜索(用 . 声明)
class属性有可能存在多个标签,建议使用select()
'''
print(soup.select('p.test'))
'''
按照标签名搜索---逐层搜索(用空格声明)
类似于前后节点(不考虑节点关系)
'''
# print(soup.select_one('a p'))
# print(soup.select('a p'))
'''
按照标签名搜索---直接子节点(用 > 声明)
类似于父子节点(考虑节点关系)
'''
# print(soup.select_one('a>p'))
# print(soup.select('a>p'))
'''
按照标签名搜索---兄弟节点(用 ~ 声明)
类似于兄弟节点(考虑节点关系)
'''
# print(soup.select_one('p.test~p'))
# print(soup.select('p.test~p'))
'''
支持链式调用
'''
# print(soup.select_one('a').select('p'))
'''
按照class属性搜索(用 . 声明)
如果class属性有多个值,使用空格隔开,需要用 . 进行填充(参考链式调用)
'''
# print(soup.select_one('a.h>p')) # 匹配失败 存在干扰项
# print(soup.select_one('a.h hh hhh hhhh>p')) # 匹配失败 无法找到标签
# print(soup.select_one('a.h.hh.hhh.hhhh>p')) # 匹配成功
'''
常用混合写法:
select() 选择父节点
select_one() 选择子节点
'''
# for element in soup.select('a'):
# print(element.select_one('p').text)
基础
文档树内容
from bs4 import BeautifulSoup
'''
bs4官方文档-string:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/#string
'''
HTML = '''
<!DOCTYPE html>
<html lang = "en">
<head>
<title>Title</title>
<a><p>Test</p></a>
</head>
</html>
'''
soup = BeautifulSoup(HTML,'lxml')
'''
Tag包含多个节点,如果没有指定某个节点,string属性会是None
a标签没有string
p标签有string
'''
# print(soup.a.string)
# print(soup.p.string)
'''
注意!!!
空格和换行都算一个节点!!!
<a><p>Test</p></a>
以上格式,能正常输出
<a>
<p>Test</p>
</a>
以上格式,bs4会认为是3个节点
'''
# print(soup.a.string)
'''
Tag包含多个节点,可以选择遍历获取全部string
strings属性---返回生成器
'''
# for string in soup.head.strings:
# print(string)
'''
【此方法能去除空格、空行】
Tag包含多个节点,可以选择遍历获取全部string
stripped_strings属性---返回生成器
'''
# for string in soup.head.stripped_strings:
# print(string)
父子节点
from bs4 import BeautifulSoup
'''
bs4官方文档-父节点:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/#id24
bs4官方文档-子节点:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/#id20
'''
HTML = '''
<!DOCTYPE html>
<html lang = "en">
<head>
<title>123</title>
<a><p>Test1</p><p>Test2</p></a>
</head>
<body>
</body>
</html>
'''
soup = BeautifulSoup(HTML,'lxml')
'''
输出该标签所有子节点---返回list
'''
# print(soup.a.contents)
'''
输出某个标签的直接子节点---返回迭代器
'''
# print(soup.a.children)
'''
遍历某个标签的直接子节点迭代器
'''
# for child in soup.a.children:
# print(child)
'''
输出某个标签的所有子孙节点
'''
# for child in soup.descendants:
# print(child)
'''
#获取当前Tag的父节点
'''
# print(soup.p.parent.name)
'''
获取当前Tag所有的父辈节点
'''
# for parent in soup.p.parents:
# print(parent.name)
'''
文本的父节点就是它自己
'''
content = soup.head.title.string
print(content.parent.name)
实战案例
待补充