爬虫 - css selector

CSS SELECTOR

功能:分析静态 html 代码,定位到具体的界面元素。

名字中有 CSS,所以与前端的 CSS 样式(Cascading Style Sheets)真的有关,

在样式中,通过选择器定位元素,进行界面渲染;而爬虫通过选择器定位元素,进行界面抓取,

二者有着类似的 API,前端开发人员能快速掌握相关内容。

安装插件

pip install beautifulsoup4

测试代码

from bs4 import BeautifulSoup

html = '''
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <span>first</span>
    <span id="a">a</span>
    <span class="b">b</span>
    <span id="c">c</span>

    <label for="d">
        <input id="d" name="d" value="d"/>
    </label>


    <span id="x">x<span id="y">y<span id="z">z</span></span></span>
    <span>last</span>

    <p title="this is content" id="p">last</p>

    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
</body>
</html>
'''

soup = BeautifulSoup(html, 'html.parser')

常规 CSS 选择

# id 查找
elements = soup.select('#a')
print(elements)

# class 查找
elements = soup.select('.b')
print(elements)

# 标签查找
elements = soup.select('input')
print(elements)

# 标签 + id 或者 标签 + class
elements = soup.select('span.b')
print(elements)

属性选择


# 查找 p 标签,存在 title 属性
elements = soup.select('p[title]')
print(elements)

# 查找 p 标签,要求 title = this is content
elements = soup.select('p[title="this is content"]')
print(elements)

# 查找 p 标签,要求 title like this%
elements = soup.select('p[title^="this"]')
print(elements)

# 查找 p 标签,要求 title like %this
elements = soup.select('p[title$="content"]')
print(elements)

# 查找 p 标签,要求 title like %is%
elements = soup.select('p[title*="is"]')
print(elements)

# 查找 p 标签,要求 title 用空格分割后包含 is
elements = soup.select('p[title~="is"]')
print(elements)

关系选择器


# 后代选择器,包含孙子级
elements = soup.select('span#x span')
print(elements)

# 子代选择器,不包含孙子级
elements = soup.select('span#x > span')
print(elements)

# 相邻兄弟选择器,标签之后第一个元素
elements = soup.select('span#a + span')
print(elements)

# 通用兄弟选择器,标签之后的所有元素
elements = soup.select('span#a ~ span')
print(elements)
```python


#### 逻辑关系

```python

# 关系与,同时满足两个条件
elements = soup.select('p[title*="is"][id="p"]')
print(elements)

# 关系或,满足其中一个条件
elements = soup.select('span#a, span.b')
print(elements)

# 关系非
elements = soup.select('span:not(#a)')
print(elements)

伪类选择器(:符号)

存在一个非常反直觉的代码,对于 'span:first-child' 和 'span:last-child',

我们下意识会觉得它们是一对:'span:first-child' 查找的是第一个 span 标签,'span:last-child' 找的应该是最后一个 span 标签,

实际并非如此,如果 span 标签内嵌其它标签,通过 'span:last-child' 找到的是:span 子级标签中的最后一个。


# 1. 同级别的第几个

# 注意:序选择器是对同级标签来说的;
# 比如:<div><p>1<p></div>  <div><p>2<p></div>
# 两个 p 标签,分布在两个 div 中,不是兄弟关系,
# 在各自的兄弟族谱中,都是第一个,因此,两个 p 标签都能通过 p:first-child 进行查找。

# 取第一个,找到 3 个元素
elements = soup.select('span:first-child')
print(elements)

# 取最后一个,找到 2 个元素
# 直觉上,功能应该与 first-child 相反,实际上,这里找的是 span 的最后一个子元素,
# 而且,与下一行的代码相比,写法完全一致,但是效果不同,日常编码中需要注意这一问题。
elements = soup.select('span:last-child')
print(elements)

# 取最后一个,找最后一个 li 标签
elements = soup.select('li:last-child')
print(elements)

# 取第一个,注意 index 从 1 开始
elements = soup.select('span:nth-child(1)')
print(elements)

# 取倒数第一个,注意 index 从 1 开始,与 :last-child 效果一致,存在相同问题
elements = soup.select('span:nth-last-child(1)')
print(elements)

# 选中父元素中唯一的标签
elements = soup.select('span:only-child')
print(elements)


# 2. 同类型的第几个

# 选中同类型的第一个标签。
elements = soup.select('li:first-of-type')
print(elements)
# 选中同类型的最后一个标签。
elements = soup.select('li:last-of-type')
print(elements)
# 选中同类型的第n个标签。
elements = soup.select('li:nth-of-type(1)')
print(elements)
# 选中同类型的倒数第n个标签。
elements = soup.select('li:nth-last-of-type(1)')
print(elements)
# 选中同类型的唯一的一个。
elements = soup.select('span:only-of-type')
print(elements)

# 3. 奇偶数选择第几个

# 选取奇数位标签
elements = soup.select('li:nth-child(2n+1)')
print(elements)
# 选取奇数位标签
elements = soup.select('li:nth-child(odd)')
print(elements)
# 选取偶数位标签
elements = soup.select('li:nth-child(even)')
print(elements)
# 选取奇数位标签
elements = soup.select('li:nth-of-type(2n+1)')
print(elements)
# 选取奇数位标签
elements = soup.select('li:nth-of-type(odd)')
print(elements)
# 选取偶数位标签
elements = soup.select('li:nth-of-type(even)')
print(elements)

伪类选择器(:符号)

按属性查找

from bs4 import BeautifulSoup

html = '''
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <input id="i1" name="i1" value="i1"></input>
    <input id="i2" name="i2" value="i2" disabled></input>
    <div></div>
    <div><h1>1</h1></div>
</body>
</html>
'''

soup = BeautifulSoup(html, 'html.parser')

elements = soup.select('input:disabled')
print(elements)

elements = soup.select('div:empty')
print(elements)

elements = soup.select('div:has(h1)')
print(elements)

posted on 2024-12-06 15:45  疯狂的妞妞  阅读(6)  评论(0编辑  收藏  举报

导航