zoukankan      html  css  js  c++  java
  • 爬虫系列 | 6、详解爬虫中BeautifulSoup4的用法

    bs4,全称BeautifulSoup 4 , 它是Python独有的一种解析方式。也就是说只有Python语言才可以通过这种方式去解析数据。

    BeautifulSoup 3 只支持Python2,所以已经被淘汰了。

    官网的介绍是这样的

    Beautiful Soup 提供一些简单的、python 式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。 Beautiful Soup 自动将输入文档转换为 Unicode 编码,输出文档转换为 utf-8 编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup 就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了。 Beautiful Soup 已成为和 lxml、html6lib 一样出色的 python 解释器,为用户灵活地提供不同的解析策略或强劲的速度。

    看起来很复杂,我用自己的理解,通俗的解释一下

    我们知道一个网页的源代码,是由多个标签组成,比如、

    、、等等组成的,而bs4就是用来帮我们精确定位标签位置,从而获取标签或者标签属性中内容的工具。bs4默认自带的解析器,但是官方推荐的是更强大 速度更快的 lxml解析器

    其他解析器的优缺点

    1561447662879877.png

    一、bs4的安装

    pip install bs4
    pip install lxml
    

    使用bs4解析时,推荐使用lxml解析器。这个在用xpath解析的时候也会用到

    二、bs4解析原理

    • 首先实例化一个BeautifulSoup对象,并且将页面源代码加载到这个对象里
    • 调用BeautifulSoup对象中的相关属性或者方法进行标签定位和数据提取
    1、如何实例化BeautifuSoup对象
    a. 导入bs4包
    from bs4 import BeautifulSoup
    
    b.实例化对象

    网页源代码,又分为本地已经持久化的HTML文件和网络上直接获取的源代码。

    如果是本地已经持久化的文件,可以通过下面的方式将源代码加载到bs4对象中

    fp = open('xxx.html', 'r', encoding='utf-8')
    # lxml:解析器
    soup = BeautifulSoup(fp, 'lxml') 
    

    如果是通过requests库获取的网页源代码,通过下面的方式进行加载

    response = requests.get(url)
    html = response.text
    soup = BeautifulSoup(html, 'lxml')
    

    c.数据解析的方法和属性

    bs4能够将复杂的HTML转换成一个树形结构,每个节点都是Python对象。

    soup.tagName(标签名): 返回的是文档中第一次出现tagName对应的标签及其相应内容

    soup.tageName1.tageName2:返回tag1中tage2的标签及其内容

    soup.find:等同于soup.tagName,返回第一个匹配到的对象

    soup.find_all:返回所有的匹配到的对象。

    通过查看源码会发现,find的本质其实就是调用了find_all, 然后返回第一个元素

    参数解释:

    • name :要查找的标签名(字符串、正则、方法、True)
    • attrs: 标签的属性
    • recursive: 递归
    • text: 查找文本
    • **kwargs :其它 键值参数
        def find(self, name=None, attrs={}, recursive=True, text=None,
                 **kwargs):
            """Return only the first child of this Tag matching the given
            criteria."""
            r = None
            l = self.find_all(name, attrs, recursive, text, 1, **kwargs)
            if l:
                r = l[0]
            return r
    

    image-20210103164834540

    上图是我从某网站截取的部分画面,翻译成HTML如下(只保留了对本次分析有用的部分,为了方便阅读删除了地址的域名信息)

    <html>
     <head><titel>测试Title</titel></head>
     <body>
      <div class="test">
          <ul>
              <li> <a href="zhaosi.html"><img src="123456789.jpg" /><p>尼古拉斯赵四</p></a> </li>
          </ul>
      </div>
      <div class="nr_zt w1180">
       <ul>
        <li> <a id="star" href="zhengshuang.html"><img src="5940f2cd6b759.jpg" /><p>郑爽</p></a> </li>
        <li> <a id="star" href="zhuyilong.html"><img src="5b56e0fabf5bf.jpg" /><p>朱一龙</p></a> </li>
        <li> <a id="star" href="zhoudongyu.html"><img src="5a28b93be8155.jpg" /><p>周冬雨</p></a> </li>
        <li> <a id="star" href="huyitian_1.html"><img src="5aa36dfbe5f61.jpg" /><p>胡一天</p></a> </li>
        <li> <a id="star" href="yiyangqianxi.html"><img src="5a28d243b0382.jpg" /><p>易烊千玺</p></a> </li>
        <li> <a id="star" href="dilireba.html"><img src="5a28b69334087.jpg" /><p>迪丽热巴</p></a> </li>
       </ul>
      </div>
     </body>
    </html>
    

    看下面几个例子

    # 获取第一个li标签
    # <li> <a href="http://www.win4000.com/mt/zhengshuang.html"><img src="http://pic1.win4000.com/tj/2017-06-14/5940f2cd6b759.jpg"/><p>郑爽</p></a> </li>
    print(soup.li)
    # # 获取第一个li标签中a标签
    # <a href="http://www.win4000.com/mt/zhengshuang.html"><img src="http://pic1.win4000.com/tj/2017-06-14/5940f2cd6b759.jpg"/><p>郑爽</p></a>
    print(soup.li.a)
    #获取第一个li标签中a标签
    print(soup.find('li').a)
    # 获取所有li标签
    print(soup.find_all('li'))
    # 获取title标签
    print(soup.title)
    # 获取a标签的父级标签
    print(soup.a.parent)
    # 获取a标签的父级标签的名字
    print(soup.a.parent.name)
    

    如何获取HTML中的href?

    分析:href是a标签中的一个属性,而a标签又在li标签中

    在bs4中提取标签中的属性可以通过attrs来获取

    from bs4 import BeautifulSoup
    
    fp = open('baidu.html', 'r', encoding='utf-8')
    soup = BeautifulSoup(fp, 'lxml')
    
    # 如果获取一个可以这样写
    result = soup.a.attrs['href']
    # zhaosi.html
    print(result)
    
    # 获取全部,可通过先获取a标签 然后遍历获取
    all_result = soup.find_all('a')
    for i in all_result:
        print(i.attrs['href'])
    
    print("* " * 40)
    #  如果我只想获取id = star的href,需要先对id进行筛选
    # 返回所有包含id=star的a标签
    star_result = soup.find_all('a', id='star')
    for i in star_result:
        print(i.attrs['href'])
    
    # 返回包含id的标签(只要有id属性,并且有值的标签都返回)
    soup.find_all(id=True)
    
    # 假设尼古拉斯赵四 不是第一个a标签中的内容.提取对应的href
    # 需要先定位class=‘test’对应div的位置
    # 方法一:
    result = soup.find('div', 'test')
    print(result.a['href'])
    
    # 方法二(class为python中关键字,因此查找html中的class属性需要添加个下划线 class_)
    result1 = soup.find('div', class_='test')
    print(result1.a['href'])
    
    # 方法三
    result2 = soup.find('div', attrs={'class': 'test'})
    
    # 获取第一个a标签中的文本内容
    print(soup.a.text)
    
    a_result = soup.find_all('a')
    for i in a_result:
        # 生成的是一个迭代器
        print(i.strings)
        print(list(i.strings))
        print(i.string)
        print(i.text)
    
    

    其他补充

    # 返回子孙节点
    # children返回迭代器
    result = soup.a.children
    for i in result:
        print(i)
    
    # 返回子孙节点, contents返回列表
    r = soup.a.contents
    print(r)
    
    # 可以通过正则对某个属性进行匹配
    # 比如返回href中以zh开头的标签
    import re
    reg = re.compile('^zh')
    result = soup.find_all(href=reg)
    print(result)
    
    

    选择器

    bs4非常强大,还支持css选择器。通过select来完成

    <html>
     <head><titel>测试Title</titel></head>
     <body>
      <div class="test">
          <ul>
              <li> <a href="zhaosi.html"><img src="123456789.jpg" /><p>尼古拉斯赵四</p></a> </li>
          </ul>
      </div>
      <div class="nr_zt w1180">
       <ul>
        <li> <a id="star" href="zhengshuang.html"><img src="5940f2cd6b759.jpg" /><p>郑爽</p></a> </li>
        <li> <a id="star" href="zhuyilong.html"><img src="5b56e0fabf5bf.jpg" /><p>朱一龙</p></a> </li>
        <li> <a id="star" href="zhoudongyu.html"><img src="5a28b93be8155.jpg" /><p>周冬雨</p></a> </li>
        <li> <a id="star" href="huyitian_1.html"><img src="5aa36dfbe5f61.jpg" /><p>胡一天</p></a> </li>
        <li> <a id="star" href="yiyangqianxi.html"><img src="5a28d243b0382.jpg" /><p>易烊千玺</p></a> </li>
        <li> <a id="star" href="dilireba.html"><img src="5a28b69334087.jpg" /><p>迪丽热巴</p></a> </li>
       </ul>
      </div>
     </body>
    </html>
    
    from bs4 import BeautifulSoup
    
    fp = open('baidu.html', 'r', encoding='utf-8')
    soup = BeautifulSoup(fp, 'lxml')
    
    # 返回一个所有a标签的列表
    result = soup.select('a')
    # 返回第一个
    result1 = soup.select('a')[0]
    
    """
    class选择器 : .className
    """
    # 一层一层的进行选择,用 > 连接  即 > : 表示一个层级
    # 输出 class = nr_zt 下ul下的li下的a标签集合
    a = soup.select('.nr_zt > ul > li > a')
    # 多个层级关联,使用 空格。
    # 输出 class= 'nr_zt' 下的a标签集合
    b = soup.select('.nr_zt a')
    
    
    """
    id选择器: # idName
    """
    result = soup.select('#star')
    
    # 通过href属性查找,返回列表
    soup.select('a[href="zhengshuang.html"]')
    
    # 获取对应标签中img标签的src值
    a = soup.select('a[href="zhengshuang.html"]')[0]
    print(a.img['src']) # 5940f2cd6b759.jpg
    

    以上就是bs4的常用操作代码,实际上在具体的爬虫过程中,匹配的方式比较灵活,所以大家也不用可以的去背,只需要记住其原理即可。

    在这里插入图片描述

  • 相关阅读:
    Pandas数据结构简要概述
    pip install PyQt5和pip install PyQt5tools安装后,找不到designer.exe路径
    解决Qt5中利用designer建立二级菜单无法输入中文的处理技巧
    事务
    大家一起讨论一下朋友网的人脉关系算法是怎么实现的
    .net程序员必须学习的10项技术
    KENDOUI控件 GRID中TEMPLATE中条件判断的使用
    Kendo Template 模板中使用KendoUI组件
    Kendo.Grid 使用POPUP时分别定义Create和Edit模板
    Kendo UI 遮罩层组件
  • 原文地址:https://www.cnblogs.com/wyl-0120/p/14300491.html
Copyright © 2011-2022 走看看