• 爬虫之数据解析


    何为数据解析
    • 概念:就是将爬取到数据中局部的指定的数据进行提取
    • 作用:实现聚焦爬虫
    • 数据解析通用原理:
      • html是用来展示数据,html中展示的数据正是我们要爬取或者采集的数据
      • 数据解析的通用原理:
        • 标签定位
        • 提取标签中存储的数据
    • 聚焦爬虫编码流程
      • 指定url
      • 发起请求
      • 获取响应数据
      • 数据解析
      • 持久化存储
    图片的获取
    • 如何爬取多媒体资源(图片,音频等)
    方式1:
    import requests
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36X-Requested-With: XMLHttpRequest'
    }
    # 获取图片地址:通常为img标签的src属性值
    img_src = 'https://pic.netbian.com/uploads/allimg/231102/092518-169888831897c3.jpg'
    # 对图片发起请求
    response = requests.get(url=img_src, headers=headers)
    # 获取图片数据:content返回的是二进制形式的响应数据
    img_data = response.content
    # 持久化存储
    with open('./demo.jpg', 'wb') as fp:
        fp.write(img_data)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    方式2:
    - ```python
      from urllib import request
      
      img_src = 'https://pic.netbian.com/uploads/allimg/231102/092518-169888831897c3.jpg'
      #urlretrieve可以直接对图片发起请求,且将请求到的图片数据进行持久化存储
      request.urlretrieve(img_src,'./456.jpg')
      ```
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    bs4
    • 环境安装:pip install bs4

    • bs4数据解析的流程

      • 1.实例化一个BeautifulSoup的对象,然后把即将被解析的页面源码数据加载到该对象中
        • BeautifulSoup(fp,‘lxml’):fp表示本地的一个文件,该种方式是将本地存储的html文件进行数据解析
        • BeautifulSoup(page_text,‘lxml’):page_text是网络请求到的页面源码数据,该种方式是直接将网络请求到的页面源码数据进行数据解析
      • 2.调用BeautifulSoup对象中相关的属性和方法实现标签定位和数据提取
    • 具体解析的操作:

      • 在当前目录下新建一个test.html文件,然后将下述内容拷贝到该文件中

        • <html lang="en">
          <head>
          	<meta charset="UTF-8" />
          	<title>测试bs4title>
          head>
          <body>
          	<div>
          		<p>百里守约p>
          	div>
          	<div class="song">
          		<p>李清照p>
          		<p>王安石p>
          		<p>苏轼p>
          		<p>柳宗元p>
          		<a href="http://www.song.com/" title="赵匡胤" target="_self">
          			<span>this is spanspan>
          		宋朝是最强大的王朝,不是军队的强大,而是经济很强大,国民都很有钱a>
          		<a href="" class="du">总为浮云能蔽日,长安不见使人愁a>
          		<img src="http://www.baidu.com/meinv.jpg" alt="" />
          	div>
          	<div class="tang">
          		<ul>
          			<li><a href="http://www.baidu.com" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村a>li>
          			<li><a href="http://www.163.com" title="qin">秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山a>li>
          			<li><a href="http://www.126.com" alt="qi">岐王宅里寻常见,崔九堂前几度闻,正是江南好风景,落花时节又逢君a>li>
          			<li><a href="http://www.sina.com" class="du">杜甫a>li>
          			<li><a href="http://www.dudu.com" class="du">杜牧a>li>
          			<li><b>杜小月b>li>
          			<li><i>度蜜月i>li>
          			<li><a href="http://www.haha.com" id="feng">凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘a>li>
          		ul>
          	div>
          body>
          html>
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
      • 有了test.html文件后,在练习如下操作

         from bs4 import BeautifulSoup
          #fp就表示本地存储的一个html文件
          fp = open('./test.html','r',encoding='utf-8')
          #解析本地存储的html文件中的内容
          #实例化BeautifulSoup对象,然后把即将被解析的页面源码数据加载到了该对象中
          soup = BeautifulSoup(fp,'lxml') #参数2,lxml是固定形式,表示指定的解析器
          #标签定位
          #方式1:soup.tagName,只会定位到符合条件的第一个标签
          tag1 = soup.title #定位到了title标签
          tag2 = soup.div
          #方式2:属性定位,find函数,findall函数
              #find('tagName',attrName='attrValue'):find只会定位到满足要的第一个标签
          tag3 = soup.find('div',class_='song')#定位class属性值为song的div标签
          tag4 = soup.find('a',id='feng')#定位id属性值为feng的a标签
              #findAll('tagName',attrName='attrValue'):可以定位到满足要求的所有标签
          tag5 = soup.findAll('div',class_='song')
          #方式3:选择器定位:soup.select('选择器')
              #id选择器:#feng  ----id为feng
              #class选择器:.song ----class为song
              #层级选择器:大于号表示一个层级,空格表示多个层级
          tag6 = soup.select('#feng') #定位到所有id属性值为feng的标签
          tag7 = soup.select('.song')#定位到所有class属性值为song的标签
          tag8 = soup.select('.tang > ul > li') #定位到了class为tang下面的ul下面所有的li标签
          tag9 = soup.select('.tang li')
          
          #提取标签中的内容
          #1.提取标签中间的内容:
              #tag.string:只可以提取到标签中直系的文本内容
              #tag.text:可以提取到标签中所有的文本内容
          # p_tag = soup.p
          # print(p_tag.string)
          # print(p_tag.text)
          # div_tag = soup.find('div',class_='song')
          # print(div_tag.text)
          
          #2.提取标签的属性值
              #tag['attrName']
          img_tag = soup.img
          print(img_tag['src']) #提取img标签的src的属性值
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    bs4案例应用:小说批量爬取
    • url:https://www.shicimingju.com/book/sanguoyanyi.html

    • 需求:将每一个章节的标题和内容进行爬取然后存储到一个文件中

      • 步骤:
        • 1.请求主页的页面源码数据
        • 2.数据解析:
          • 章节标题
          • 章节详情页的链接
        • 3.解析章节详细内容
        • 4.将解析的章节标题和内容进行存储
    from bs4 import BeautifulSoup
    import requests
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'
    }
    # 首页地址
    main_url = 'https://www.shicimingju.com/book/sanguoyanyi.html'
    # 发起请求,获取了主页页面源码
    response = requests.get(url=main_url, headers=headers)
    response.encoding = 'utf-8'
    # response.encoding = 'gbk'
    page_text = response.text
    # print(page_text)
    # 或者使用获得的进行解码
    # print(response.content.decode(response.encoding))
    
    # 数据解析:章节标题+详情页链接
    soup = BeautifulSoup(page_text, 'lxml')
    a_list = soup.select('.book-mulu > ul > li > a')
    fp = open('./sanguo.txt', 'w', encoding='utf-8')
    #encode 是编码
    # decode是解码
    for a in a_list:
        title = a.string  # 章节标题
        detail_url = 'https://www.shicimingju.com' + a['href']  # 详情页地址
        # 请求详情页的页面源码数据
        response = requests.get(url=detail_url, headers=headers)
        response.encoding = 'utf-8'
        detail_page_text = response.text
        # 解析:解析章节内容
        d_soup = BeautifulSoup(detail_page_text, 'lxml')
        div_tag = d_soup.find('div', class_='chapter_content')
        content = div_tag.text  # 章节内容
        fp.write(title + ':' + content + '\n')
        print(title, '爬取保存成功!')
    fp.close()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    Xpath
    • 环境安装:pip install lxml

    • xpath解析的编码流程

      • 1.创建一个etree类型的对象,然后把即将被解析的页面源码数据加载到该对象中
      • 2.调用etree对象的xpath方法结合着不同形式的xpath表达式,进行标签定位和数据提取
    • xpath表达式如何理解?

      • html中的标签是遵从树状结构的。
        from lxml import etree #如果这种方式报错,使用下面方式导入etree
        # from lxml.html import etree
        fp = open('test.html','r')
        #1.将本地存储好的文件中的数据加载到etree对象中进行数据解析
        tree = etree.parse(fp)
        #2.调用etree对象的xpath方法结合不同形式的xpath表达式进行标签定位和数据提取
        #xpath返回的一定是列表,列表中存储的是定位到的标签对象
        # title_tag = tree.xpath('/html/head/title')
        # title_tag = tree.xpath('/html//title')
        # title_tag = tree.xpath('//head/title')
        # title_tag = tree.xpath('//title') #推荐
        #最左侧为/:表示必须从树的根标签(html标签)开始进行定位
        #最左侧为//:可以从任意位置进行标签的相对位置定位
        #非最左侧的/:表示一个层级
        #非最左侧的//:表示多个层级
        # tag = tree.xpath('//div') #定位所有的div标签
        
        #属性定位:根据标签的属性定位标签
        #//tagName[@attrName="attrValue"]
        # tag = tree.xpath('//div[@class="song"]')#定位class属性值为song的div标签
        # tag = tree.xpath('//a[@id="feng"]')
        # tag = tree.xpath('//div[@class="tang"]/ul/li/a[@id="feng"]')
        #索引定位:索引是从1开始的
        # tag = tree.xpath('//div[@class="tang"]/ul/li[3]')#定位到第三个li标签
        #获取定位到标签中的文本内容
            # /text()获取标签中直系的文本内容:返回的列表中只会有一个列表元素
            # //text()获取标签中所有的文本内容:通常返回列表中存在多个元素
        # tag = tree.xpath('//div[@class="song"]/p[3]/text()')
        # tag = tree.xpath('//div[@class="song"]//text()')
        #获取定位到标签中的属性值://tag/@attrName
        tag = tree.xpath('//img/@src')
        print(tag)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    Xpath案例应用:
    • http://pic.netbian.com/4kmeinv/

      • 将爬取到的图片存储到指定的文件夹中

      • 爬取第一页

    from lxml import etree
    import requests
    from fake_useragent import UserAgent
    
    ua = UserAgent()
    import os
    
    # 新建一个文件夹
    dirName = 'girls'
    if not os.path.exists(dirName):  # 如果文件夹不存在,则新建,否则不新建
        os.mkdir(dirName)
    headers = {
        'User-Agent': ua.chrome}
    
    url = 'https://pic.netbian.com/4kmeinv/index.html'
    response = requests.get(url=url, headers=headers)
    response.encoding = 'gbk'
    
    page_text = response.text
    # response.encoding='gbk'
    # print(page_text) # ISO-8859-1
    # 数据解析:图片地址+图片名称
    tree = etree.HTML(page_text)  # HTML()专门用来解析网络请求到的页面源码数据
    # 该列表中存储的是每一个li标签
    li_list = tree.xpath('//div[@class="slist"]/ul/li')
    for li in li_list:
        # 局部解析:将li标签中指定的内容解析出来
        # 使用 . 调用当前标签 凭借
        # 每一次都是 获得列表
        img_title = li.xpath('./a/b/text()')[0] + '.jpg'  # 左侧./表示xpath的调用者对应的标签
        img_src = 'https://pic.netbian.com' + li.xpath('./a/img/@src')[0]
        print(img_title, img_src)
        # 对图片发起请求,存储图片数据
        img_data = requests.get(url=img_src, headers=headers).content
        # girls/123.jpg
        img_path = dirName + '/' + img_title
        print(img_path)
        # with open(img_path, 'wb') as fp:
        #     fp.write(img_data)
        # print(img_title, '下载保存成功!')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
  • 相关阅读:
    【Vue】从零搭建一个Vue项目
    选择类排序法
    Redis高可用集群(哨兵、集群)
    Learn Prompt-Prompt 高级技巧:AI-town 虚拟小镇
    Kotlin 协程之取消与异常处理探索之旅(下)
    Cholesterol-PEG-Acid 胆固醇聚乙二醇羧基 储存于低温干燥环境下
    设计模式案例
    解决ROS2报错colcon build: Duplicate package names not supported
    基于SSM的共享客栈管理系统的设计与实现
    Spring - IoC 容器之 Bean 的生命周期
  • 原文地址:https://blog.csdn.net/ak_bingbing/article/details/134299614