美文网首页
63.4-find系方法参数、css选择器、Jsonpath

63.4-find系方法参数、css选择器、Jsonpath

作者: BeautifulSoulpy | 来源:发表于2020-08-29 11:33 被阅读0次

让适合的人走进你的生活吧,让旧梦逝去吧,让不合适的那个离开吧。人生,看轻看淡多少,痛苦就离开你多少。因为看轻,所以快乐!


2. keyword传参

使用关键字传参,如果参数名不是find系函数已定义的位置参数名,参数会被kwargs收集并被当做标签的属性来搜索(拥有ID属性的标签)。
属性的传参可以是字符串、正则表达式对象、True、列表。

    div:Tag = soup.div.div

    print(soup.find_all(id='first')) # id为first的所有节点列表
    print('--------------------------------------')
    #print(soup.find_all(id=re.compile('\w+'))) # 相当于找有id的所有节点
    print('-------------------------')
    #print(soup.find_all(id=True)) # 所有有id的节点
    print('--------------------------------------')
    print(list(map(lambda x:x['id'], soup.find_all(id=True))))  # 拥有id属性的标签;
    print('--------------------------------------')
    print(soup.find_all(id=['first', re.compile(r'^sec')])) # 指定id的名称列表
    print(soup.find_all(id=True, src=True)) # 相当于条件and,既有id又有src属性的节点列表
#-----------------------------------------------------------------
[<p id="first">字典</p>]
--------------------------------------
-------------------------
--------------------------------------
['main', 'first', 'second', 'bg1', 'bg2']
--------------------------------------
[<p id="first">字典</p>, <p id="second">列表</p>]
[<img id="bg1" src="http://www.magedu.com/"/>, <img id="bg2" src="http://httpbin.org/"/>]
3. css的class的特殊处理

class是Python关键字,所以使用 class_ 。class是多值属性,可以匹配其中任意一个,也可以完全匹配。

    print(soup.find_all(class_="content"))  # 全部内容
    print('---------------------------')
    print(soup.find_all(class_="title"))  # 可以使用任意一个css类
    print(soup.find_all(class_="highlight"))  # 可以使用任意一个css类
    print(soup.find_all(class_="highlight title"))  # 顺序错了, 找不到
    print(soup.find_all(class_="title highlight"))  # 顺序一致, 找到, 就是字符串完全匹配
#-------------------------------------------------------------------------------------------------
[<div class="content">
<p id="first">字典</p>
<p id="second">列表</p>
<input name="_csrf" type="hidden" value="7139e401481ef2f46ce98b22af4f4bed"/>
<!-- comment -->
<img id="bg1" src="http://www.magedu.com/"/>
<img id="bg2" src="http://httpbin.org/"/>
</div>]
---------------------------
[<h3 class="title highlight"><a href="http://www.python.org">python</a>高级班</h3>]
[<h3 class="title highlight"><a href="http://www.python.org">python</a>高级班</h3>]
[]
[<h3 class="title highlight"><a href="http://www.python.org">python</a>高级班</h3>]

4. attrs参数

属性:attrs接收一个字典, 字典的key为属性名, value可以是字符串、正则表达式对象、True、列表

    print(soup.find_all(attrs={'class':'title'} ) )
    print(soup.find_all(attrs={'class':'highlight'} ) )
    print(soup.find_all(attrs={'class':'title highlight'} ) )
    print('---------------------------')
    print(soup.find_all(attrs={'id':re.compile('bg'), 'src':True} ) )  #  相当于 bg and  src
    # print(soup.find_all(attrs={'id':True} ) )
    print('---------------------------')
    print(soup.find_all(attrs={'id':re.compile(r'\d$')} ) )
# ----------------------------------------------------
[<h3 class="title highlight"><a href="http://www.python.org">python</a>高级班</h3>]
[<h3 class="title highlight"><a href="http://www.python.org">python</a>高级班</h3>]
[<h3 class="title highlight"><a href="http://www.python.org">python</a>高级班</h3>]
---------------------------
[<img id="bg1" src="http://www.magedu.com/"/>, <img id="bg2" src="http://httpbin.org/"/>]
---------------------------
[<img id="bg1" src="http://www.magedu.com/"/>, <img id="bg2" src="http://httpbin.org/"/>]
5. text参数

可以通过text参数搜索文档中的字符串内容,接受字符串、正则表达式对象、True、列表

    print(list(map('body', soup.find_all(text=re.compile('\w+')))))
    print(list(map(lambda x: (type(x), x), soup.find_all(text=re.compile('\w+')))))
    print('-----------------------------------------------|')
    print(list(map(lambda x: (type(x), x), soup.find_all(text=re.compile('[a-z]+')))))
    print(soup.find_all(re.compile(r'^(h|p)'), text=re.compile('[a-z]+')))  # 相当于过滤出Tag对象,并看 p标签,text为字母的
#-------------------------------------------------------------------
[(<class 'bs4.element.Doctype'>, 'html'), (<class 'bs4.element.NavigableString'>, '首页'), (<class 'bs4.element.NavigableString'>, '马哥教育欢迎您'), (<class 'bs4.element.NavigableString'>, 'python'), (<class 'bs4.element.NavigableString'>, '高级班'), (<class 'bs4.element.NavigableString'>, '字典'), (<class 'bs4.element.NavigableString'>, '列表'), (<class 'bs4.element.Comment'>, ' comment '), (<class 'bs4.element.NavigableString'>, 'bottom')]
-----------------------------------------------|
[(<class 'bs4.element.Doctype'>, 'html'), (<class 'bs4.element.NavigableString'>, 'python'), (<class 'bs4.element.Comment'>, ' comment '), (<class 'bs4.element.NavigableString'>, 'bottom')]
[<p>bottom</p>]
6. limit参数

限制返回结果的数量

    print(soup.find_all(id=True))  # 返回列表中有3个结果
7. recursive 参数

默认是递归搜索所有子孙节点,如果不需要请设置为False

8. 简化写法

find_all()是非常常用的方法,可以简化省略掉

    print(soup('img'))  # 所有img标签对象的列表,不等价于soup.a
    print(soup.img)  # 深度优先第一个img
    print(soup.a.find_all(text=True))  # 返回文本
    print(soup.a(text=True))  # 返回文本,和上面等价
    print(soup('a', text=True))  # 返回a标签对象
    print(soup.find_all('img', attrs={'id': 'bg1'}))
    print(soup('img', attrs={'id': 'bg1'}))  # find_all的省略
    print(soup('img', attrs={'id': re.compile('1')}))
# -----------------------------------------------------------------
[<img id="bg1" src="http://www.magedu.com/"/>, <img id="bg2" src="http://httpbin.org/"/>]
<img id="bg1" src="http://www.magedu.com/"/>
['python']
['python']
[<a href="http://www.python.org">python</a>]
[<img id="bg1" src="http://www.magedu.com/"/>]
[<img id="bg1" src="http://www.magedu.com/"/>]
[<img id="bg1" src="http://www.magedu.com/"/>]
9. find方法

find( name , attrs , recursive , text , **kwargs )

参数几乎和find_all一样。
找到了, find_all返回一个列表, 而find返回一个单值, 元素对象。
找不到, find_all返回一个空列表, 而find返回一个None。

    print(soup.find('img',attrs = {'id':'bg1'} ).attrs.get('src','mage du') )
    print(soup.find('img',attrs = {'id':'bg1'} ).get('src') )  # 简化了attrs
    print(soup.find('img',attrs = {'id':'bg1'} ) ['src'] )
----------------------------------------------------------
http://www.magedu.com/
http://www.magedu.com/
http://www.magedu.com/
3.5 CSS选择器 ***(重点)

和JQuery一样,可以使用CSS选择器来查找节点
使用soup.select()方法,select方法支持大部分CSS选择器,返回列表。
CSS中,标签名直接使用,类名前加.点号,id名前加#井号。

from bs4 import BeautifulSoup
from bs4.element import Tag
import re

with open('./test.html', encoding='utf-8') as f:
    soup = BeautifulSoup(f, 'lxml')
    # 元素选择器
    print(1, soup.select('p'))  # 所有的p标签

    # 类选择器
    print(2, soup.select('.title'))

    # 使用了伪类
    # 直接子标签是p的同类型的所有p标签中的第二个
    # (同类型)同标签名p的第2个,伪类只实现了nth-of-type,且要求是数字
    print(3, soup.select('div.content > p:nth-of-type(2)'))  # 只实现了这个伪类

    # id选择器
    print(4, soup.select('p#second'))
    print(5, soup.select('#bg1'))

    # 后代选择器
    print(6, soup.select('div p'))  # div下逐层找p
    print(7, soup.select('div div p'))  # div下逐层找div下逐层找p

    # 子选择器,直接后代
    print(8, soup.select('div > p'))  # div下直接子标签的p,有2个

    # 相邻兄弟选择器
    print(9, soup.select('div p:nth-of-type(1) + [src]'))  # 返回[]

    # 普通兄弟选择器
    print(10, soup.select('div p:nth-of-type(1) ~ [src]'))  # 返回2个img

    # 属性选择器
    print(11, soup.select('[src]')) # 有属性src
    print(12, soup.select('[src="/"]')) # 属性src等于/
    print(13, soup.select('[src="http://www.magedu.com/"]')) # 完全匹配
    print(14, soup.select('[src^="http://www"]')) # 以http://www开头
    print(15, soup.select('[src$="com/"]')) # 以com/结尾
    print(16, soup.select('img[src*="mage du"] ') )
    print(17, soup.select('img[src*=".com"] ') )
    print(18, soup.select('[class="title highlight"] ') )
    print(19, soup.select('[class~=title] ') )  # 多值属性中有一个title
------------------------------------------------------------
1 [<p id="first">字典</p>, <p id="second">列表</p>, <p>bottom</p>]
2 [<h3 class="title highlight"><a href="http://www.python.org">python</a>高级班</h3>]
3 [<p id="second">列表</p>]
4 [<p id="second">列表</p>]
5 [<img id="bg1" src="http://www.magedu.com/"/>]
6 [<p id="first">字典</p>, <p id="second">列表</p>]
7 [<p id="first">字典</p>, <p id="second">列表</p>]
8 [<p id="first">字典</p>, <p id="second">列表</p>]
9 []
10 [<img id="bg1" src="http://www.magedu.com/"/>, <img id="bg2" src="http://httpbin.org/"/>]
11 [<img id="bg1" src="http://www.magedu.com/"/>, <img id="bg2" src="http://httpbin.org/"/>]
12 []
13 [<img id="bg1" src="http://www.magedu.com/"/>]
14 [<img id="bg1" src="http://www.magedu.com/"/>]
15 [<img id="bg1" src="http://www.magedu.com/"/>]
16 []
17 [<img id="bg1" src="http://www.magedu.com/"/>]
18 [<h3 class="title highlight"><a href="http://www.python.org">python</a>高级班</h3>]
19 [<h3 class="title highlight"><a href="http://www.python.org">python</a>高级班</h3>]
3.6. 获取文本内容

搜索节点的目的往往是为了提取该节点的文本内容, 一般不需要HTML标记, 只需要文字

from bs4 import BeautifulSoup

with open('./test.html', encoding='utf-8') as f:
    soup = BeautifulSoup(f, 'lxml')
    # 元素选择器
    ele = soup.select('div') # 所有的div标签
    print(ele[0].string, end='\n------------\n') # 内容仅仅只能是文本类型,否则返回None
    print(list(ele[0].strings), end='\n------------\n') # 迭代保留空白字符
    print(list(ele[0].stripped_strings), end='\n------------\n') # 迭代不保留空白字符
    print(ele[0], end='\n------------\n')
    print(ele[0].text, end='\n------------\n') # 本质上就是get_text(),保留空白字符的strings
    print(ele[0].get_text(), end='\n------------\n') # 迭代并join,保留空白字符,strip默认为False
    print(ele[0].get_text(strip=True)) # 迭代并join,不保留空白字符

2. Json解析

拿到一个Json字符串,如果想提取其中的部分内容,就需要遍历了。在遍历过程中进行判断。

还有一种方式,类似于XPath,叫做JsonPath。

安装
$ pip install jsonpath
官网 http://goessner.net/articles/JsonPath/ (查询 example)

下表中列出了对应了JSONPath以及对应的XPath用法

XPath JsonPath 说明
/ $ 根节点
. @ 现行节点
/ .or[] 取子节点
.. n/a 取父节点,Jsonpath未支持
// .. 就是不管位置,选择所有符合条件的条件
* * 匹配所有元素节点
@ n/a 根据属性访问,Json不支持,因为Json是个Key-value递归结构,不需要属性访问。
[] [] 迭代器标示(可以在里边做简单的迭代操作,如数组下标,根据内容选值等)
\ | [,] 支持迭代器中做多选。
不支持 [start:stop:step] 切片
[] ?() 支持过滤操作.
n/a () 支持表达式计算
() n/a 分组,JsonPath不支持

依然用豆瓣电影的热门电影的Json, 找到得分高于8分的
https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&page_limit=50&page_start=0

# subjects对象 
{
    subjects:
        [
            {
                rate: "8.3",
                cover_x: 2309,
                title: "爱你,西蒙",
                url: "https://movie.douban.com/subject/26654498/",
                playable: false,
                cover:
                    "https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2523592367.webp",

                id: "26654498",
                cover_y: 3464,
                is_new: false
            },
            {
                rate: "8.3",
                cover_x: 3578,
                title: "暴裂无声",
                url: "https://movie.douban.com/subject/26647117/",
                playable: true,
                cover:
                    "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2517333671.webp",
                id: "26647117",
                cover_y: 5078,
                is_new: false
            }
        ]
}




import requests,simplejson
from jsonpath import jsonpath
from lxml import etree
from bs4 import BeautifulSoup

# ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36"
url = "https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&page_limit=50&page_start=0"

req = requests.request('GET',url,headers={'User-agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36"})

if req:
    text = req.text   # 分析的 HTML
    # soup = BeautifulSoup(text,'lxml')   # soup 会套一层html 标签;
    subjects = simplejson.loads(text)
    print(subjects)
#-----------------------------------------------------------------subject对象当前级别 50 个
{'subjects': [{'rate': '5.2', 'cover_x': 1080, 'title': '釜山行2:半岛', 'url': 'https://movie.douban.com/subject/30299515/', 'playable': False, 'cover': 'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2588307420.jpg', 'id': '30299515', 'cover_y': 1539, 'is_new': False},  {'rate': '6.7', 'cover_x': 1050, 'title': '烂故事', 'url': 'https://movie.douban.com/subject/34958737/', 'playable': False, 'cover': 'https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2601922615.jpg', 'id': '34958737', 'cover_y': 1500, 'is_new': False}]}

    rs1 = jsonpath(subjects,'$..title')  # 从根开始任意层的title  50 个
    print(rs1,len(rs1))
#----------------------------------------------------------
['釜山行2:半岛', '铁雨2:首脑峰会', '四平青年之三傻罪途', '超人:明日之子', '夏日国度']

    rs2 = jsonpath(subjects,'$..subjects[?(@.rate>"8")]')   # 查询subjects中 评分大于8的电影 ;
    rs2title = jsonpath(subjects,'$..subjects[?(@.rate>"8")].title')  # 去大于8分电影的标题;
    print(rs2)
    print(rs2title[:5])
#----------------------------------------------------------
[{'rate': '8.6', 'cover_x': 2977, 'title': '极速车王', 'url': 'https://movie.douban.com/subject/6538866/', 'playable': False, 'cover': 'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2614997281.jpg', 'id': '6538866', 'cover_y': 4410, 'is_new': False}, {'rate': '8.5', 'cover_x': 3000, 'title': '1917', 'url': 'https://movie.douban.com/subject/30252495/', 'playable': False, 'cover': 'https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2615015805.jpg', 'id': '30252495', 'cover_y': 4200, 'is_new': False}, {'rate': '8.0', 'cover_x': 1080, 'title': '马丁·伊登', 'url': 'https://movie.douban.com/subject/26952994/', 'playable': False, 'cover': 'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2578760530.jpg', 'id': '26952994', 'cover_y': 1543, 'is_new': False}]
['极速车王', '1917', '乔乔的异想世界', '少年的你', '进击的巨人:编年史']


异步请求的数据在XHR中,request请求的html不一定有我们想要的数据;


思路
找到title非常容易, 但是要用其兄弟节点rate判断是否大于8分, 就不好做了。
能够从父节点下手, subjects的多个子节点中, 要用[] , 某一个当前节点的rate和字符串8比较来过滤的得到符合要求的subjects的子节点, 取这个子节点的title。

能否通过其他地方获取信息

相关文章

  • 63.4-find系方法参数、css选择器、Jsonpath

    让适合的人走进你的生活吧,让旧梦逝去吧,让不合适的那个离开吧。人生,看轻看淡多少,痛苦就离开你多少。因为看轻,所以...

  • jsonpath使用

    使用: 1、jsonpath方法需要两个参数 参数1:数据参数2:jsonpath表达式 2、注意点: 3、jso...

  • 爬虫基础系列BeautifulSoup——css选择器(4)

    css选择器简介 CSS选择器类型:标签选择器、类选择器、id选择器 方法:select() ① 结果:注意是一个...

  • CSS入门

    CSS CSS基本语法 CSS定义方法是:  选择器{属性:值;属性:值;属性:值}  选择器是将样式和页面元素关...

  • jQuery选择器和监听事件

    筛选选择器和方法 筛选选择器 $('p:first').css('background','skyblue'); ...

  • css使用方法

    css基本语法 css的定义方法是:选择器 { 属性:值; 属性:值; 属性:值;} 例: css页面引入方法: ...

  • css

    css基本语法及页面引用 css基本语法 css的定义方法:选择器{属性:值;属性:值;属性:值;}选择器是将样...

  • CSS选择器

    CSS 元素选择器CSS 选择器分组CSS 类选择器详解CSS ID 选择器详解CSS 属性选择器详解CSS 后代...

  • python接口自动化小技巧-参数提取

    如何快速提取json参数? 例如: 1.字典原生方法 dict[key] 2.jsonpath -如何测试提取是否...

  • 学习CSS,这些内容你都知道了吗?

    CSS介绍 引入css样式表方法 CSS选择器 CSS常用属性 CSS介绍: CSS全称是(Cascading S...

网友评论

      本文标题:63.4-find系方法参数、css选择器、Jsonpath

      本文链接:https://www.haomeiwen.com/subject/ensdsktx.html