Python爬虫对数据的四大解析方式

本文详细介绍了在爬虫中使用正则表达式、BeautifulSoup库(特别是bs4模块)和XPath进行数据解析的方法,包括通过正则获取图片地址,以及利用BeautifulSoup处理HTML结构定位和提取标签内容、属性数据。
摘要由CSDN通过智能技术生成

解析

  • 对数据的四大解析方式
    • 正则
    • bs4
    • xpath
    • pyquery

正则

  • 实例:
  • import requests
    import re
    headers = {
        'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36'
    }
    url = 'http://sc.chinaz.com/tag_tupian/YaZhouMeiNv.html'
    page_text = requests.get(url,headers=headers).text #获取字符串形式的响应数据
    #通过正则进行图片地址的解析
    ex = '<a.*?<img src2="(.*?)" alt.*?</a>'
    img_src_list = re.findall(ex,page_text,re.S)#re.S处理回车
    
  • 正则是以前学习过的内容,不做过多的叙述

bs4

  • bs4的下载
    pip install bs4
    
  • bs4的介绍
    • 为什么需要在爬虫中使用数据解析?
      • 就是为了可以实现聚焦爬虫
    • 数据解析的通用原理是什么?(解析的数据只会存在于标签之间或者属性中)
      • html是用来展示数据。
      • 原理流程:
        • 标签定位
        • 数据的提取
  • 有如下html供练习bs4 以及xpath用
    <html lang="en">
    <head>
    	<meta charset="UTF-8" />
    	<title>测试bs4</title>
    </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 span</span>
    		宋朝是最强大的王朝,不是军队的强大,而是经济很强大,国民都很有钱</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>
    
  • bs4的使用
    • 实例化一个bs4对象

      from bs4 import BeautifulSoup
      f = open('b.html','rb')
      
      soup = BeautifulSoup(f,'lxml')  # 方式一 ,给一个文件句柄,解析本地的文件
      soup = BeautifulSoup(response.text,'lxml')  # 方式二,给一个从网页中得到的内容
      
      • 两种方式

      • 方式1:
        BeautifulSoup(fp,‘lxml’):解析本地存储的html文件

      • 方式2:

        • BeautifulSoup(page_text,‘lxml’):解析互联网上请求到的页面数据)
  • 定位

    • 标签定位
      • soup.标签名,返回的是第一个标签
      from bs4 import BeautifulSoup
      f = open('b.html','rb')
      soup = BeautifulSoup(f,'lxml')  # 方式一 ,给一个文件句柄,解析本地的文件
      print(soup.div)
      
      '''
      <div>
      <p>百里守约</p>
      </div>
      '''
      
    • 属性定位
      • soup.find find是只找一个
      from bs4 import BeautifulSoup
      f = open('b.html','rb')
      soup = BeautifulSoup(f,'lxml')  # 方式一 ,给一个文件句柄,解析本地的文件
      
      print(soup.find('div',class_ = 'song'))
      print(soup.find('a',id='feng'))
      
      """
      <div class="song">
      <p>李清照</p>
      <p>王安石</p>
      <p>苏轼</p>
      <p>柳宗元</p>
      <a href="http://www.song.com/" target="_self" title="赵匡胤">
      <span>this is span</span>
      		宋朝是最强大的王朝,不是军队的强大,而是经济很强大,国民都很有钱</a>
      <a class="du" href="">总为浮云能蔽日,长安不见使人愁</a>
      <img alt="" src="http://www.baidu.com/meinv.jpg"/>
      </div>
      
      
      
      
      <a href="http://www.haha.com" id="feng">凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘</a>
      """
      
      
      • soup.findall 跟find差不多,不过这个是找多个,得到的是列表
      print(soup.find_all('a',class_ = 'du'))
      
      <a class="du" href="">总为浮云能蔽日,长安不见使人愁</a>
      
    • 注意:
      • 在找类属性的时候用的是class_ 要加一个小划线,因为class是关键
    • 选择器定位
      • select
      print(soup.select('#feng'))  #根据id选择器定位a标签
      print(soup.select('.song')) #定位class为song的标签
      
      #层级选择器
      
      print(soup.select('.tang > ul > li > a')) # >表示一个层级,一层一层的向下
      print(soup.select('.tang a')) #空格表示多个层级
      
      
  • 数据的提取

    • 提取标签中存在的数据

      • .string:取出标签直系的文本内容
      print(soup.p.string)
      
      '''
      百里守约
      '''
      
      • .text:取出标签中所有的文本内容
      print(soup.div.text)
      
      """
      百里守约
      """
      
    • 提取标签属性中存储的数据

      • tagName[‘attrName’]
      print(soup.find('a')['href'])
      
      """
      http://www.song.com/
      """
      
  • bs4爬取练习

    • 示例

      • 使用bs4解析爬取三国演义整片小说内容 链接
      import requests
      from bs4 import BeautifulSoup
      
      url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
      
      rs = requests.get(url = url)
      rs = BeautifulSoup(rs.text,'lxml')
      lis_bookmulu = rs.select('.book-mulu > ul > li > a')
      for site in lis_bookmulu:
          name = site.string # 每一章的名称
          is_url = 'http://www.shicimingju.com' + site['href'] # 详细的Url
          a = requests.get(url=is_url)
          b = BeautifulSoup(a.text,'lxml')
          down_load = b.find('div',class_= 'chapter_content').text
          with open('小说/{}.txt'.format(name),'w',encoding='utf-8') as f:
              f.write(down_load)
          break
      
      • 特别憨憨的一件事UnicodeEncodeError: 'gbk' codec can't encode character '\xa0' in position 4: illegal multibyte sequence出现这个报错,百度半小时发现是自己没加encoding='utf-8'当成对字节的操作了

xpath

  • html标签结构

    • 是一个树状的结构
  • xpath解析原理

    • 实例化一个etree对象,且将即将被解析的数据加载到该对象中
      • 解析本地存储的html文档:
        • etree.parse(‘fileName’)
      • 解析网上爬取的html数据:
        • etree.HTML(page_text)
    • 使用etree对象中的xpath方法结合着不同的xpath表达式实现标签定位和数据提取
  • xpath安装

    pip install lxml
    
  • xpath 使用

    • 实例化
    from lxml import etree
    
    tre = etree.parse('b.html')  # 方式一 解析本地的文件
    tre = etree.HTML('page_text')  # 方式二 解析网络的内容
    
    print(tre)
    
    """
    <lxml.etree._ElementTree object at 0x000001FDDC3AFF08>
    """
    # 得到的是对象
    
    • 标签定位
      • 最左侧的/:必须要从根标签开始逐层的定位目标标签
      • 非最最侧的/:表示一个层级
      from lxml import etree
      tre = etree.parse('b.html')  # 方式一 解析本地的文件
      print(tre.xpath('/html/head'))
      print(tre.xpath('/html/body'))
      
      
      • 最左侧的//:可以从任意位置定义目标标签
      print(tre.xpath('//div/p'))  # 找到任意div下的p标签
      
      """
      [<Element p at 0x21a9b954588>, <Element p at 0x21a9b995a88>, <Element p at 0x21a9b995d88>, <Element p at 0x21a9b99aa48>, <Element p at 0x21a9b99a308>]
      """
      
      • 非最左侧的//:表示多个层级
      print(tre.xpath('/html//meta'))
      
      """
      [<Element meta at 0x1cebd1d4588>]
      
      """
      
      # //表示中间隔着多个的层级
      
      • 属性定位
      # 定位到 class属性为 du 的a标签
      print(tre.xpath('//a[@class ="du"]'))
      
      # 定位到 id属性为feng 的a标签
      print(tre.xpath('//a[@id ="feng"]'))
      
      
      • 索引定位
      print(tre.xpath('//li[1]'))
      # 索引从1开始
      
      • 模糊匹配

        不常用,了解就可以

      //div[contains(@class, "ng")] 定位到class属性值中包含ng的div标签
      - //div[starts-with(@class, "ta")] 定位到class属性值中是以ta开头的div标签
      
    • 数据提取
      • 取标签中的数据

        • /text():直系文本内容
        print(tre.xpath('//a[@id="feng"]/text()')[0])
        
        # 返回的是一个列表,要用[]来取值,虽然当中只有一个值 
        
        • //text():所有的文本内容
        print(tre.xpath('//div[@class="song"]//text()'))
        
        # 取得下面所有的文本内容
        
      • 取属性的数据

        • tagName/@attrName
        print(tre.xpath('//a[@id="feng"]/@href')[0])
        
        print(tre.xpath('//div[@class = "song"]/a[1]/@title'))
        
        """
        http://www.haha.com
        ['赵匡胤']
        
        """
        # 图片就取src
        
  • 补充

    • 一个页面中的两个xpath表达式可以用 | 来提升通用性
    • xpath表达式中不可以出现tbody标签
  • 练习题

    import requests
    from lxml import etree
    
    url = 'http://pic.netbian.com/4kdongwu/index_%d.html'
    
    for i in range(1,6):
        if i == 1:
            new_url = 'http://pic.netbian.com/4kdongwu/index.html'
        else:
            new_url = url%i
    
        rs = requests.get(url=new_url)
        rs.encoding = 'gbk'
        page_text = rs.text
        tree = etree.HTML(page_text)
        img_list = tree.xpath('//ul[@class = "clearfix"]/li')
    
        for img in img_list:
            img_url = 'http://pic.netbian.com' + img.xpath('./a/@href')[0]
            img_name = img.xpath('./a/img/@alt')[0]
            rs_img = requests.get(url = img_url)
            big_img = etree.HTML(rs_img.text)
            img_b = big_img.xpath('//*[@id="img"]/img')[0]
            down_load = 'http://pic.netbian.com' + img_b.xpath('./@src')[0]  # 大图的下载本地
            img_down_load = requests.get(url=down_load) # 对大图的下载地址发请求
    
            with open('img/{}.jpg'.format(img_name),'wb') as f:
                f.write(img_down_load.content)
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海绵不会逆向

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值