zoukankan      html  css  js  c++  java
  • 三种数据解析方式

    数据解析:

    - 正则
    - bs4
    - xpath

    xpath在爬虫中的使用流程

    -1. 下载: pip install lxml
    -2. 导包 from lxml import etree
    -3. 创建etree对象进行指定数据的解析  (如果HTML文件格式或语法有问题的话,etree对象会创建失败)
        -本地:etree=etree.parse('本地文件路径')
            etree.xpath('xpath表达式')
        -网络:etree=etree.HTML('网络请求到的页面数据")
             etree.xpath('xpath表达式')

    常用的xpath表达式:

    tip : //双斜杠是相对路径,指的是当前页面的所有,比如//a 获取所有的a标签 ,/单斜杠是绝对路径,指的是直系子标签 属性定位:

    #找到class属性值为song的div标签
    //div[@class="song"]
    

    层级&索引定位:

    #找到class属性为tang的div的直系子标签ul下的第二个子标签li下的直系子标签a
    //div[@class="tang"]/ul/li[2]/a
    

    逻辑定位:

    #找到href属性值为空且class属性值为du的a标签
    //a[@href="" and @class="du"]
    

    模糊匹配: //div[contains(@class,"ng")] //div[start-with(@class,"ta")]

    取文本:

    #  /表示获取某个标签下的文本内容
      //表示获取某个标签下的文本内容和所有子标签下的文本内容
      //div[@class="song"]/p[1]/text()
      //div[@class="tang"]//text()
    

    取属性: //div[@class="tang"]//li[2]/a/@href

     

    ## 当前节点(./): 如./book 表示选择当前节点下的 book 节点集合

    父节点(../): 如../book表示选择当前节点的父节点下的book节点集合

    根元素(/): 如/book表示选择从文档根节点下的book节点集合.

    from lxml import etree
    
    #xpath 函数返回的总是一个列表
    
    #创建etree对象进行制定数据解析
    tree = etree.parse('./test.html')
    #属性定位:根据指定属性定位到指定的节点标签
    tree.xpath('//div[@class="song"]')
    # 层级&索引定位:找到class属性为tang的div的直系子标签ul下的第二个子标签li下的直系子标签a。 【是从1开始的】
    tree.xpath('//div[@class="tang"]/ul/li[2]/a')
    # 逻辑定位:
    tree.xpath('//a[@href="" and @class="du"]')
    # 模糊匹配:
    tree.xpath('//div[contains(@class,"ng")]')    #找到class属性里包含ng的class
    tree.xpath('//div[start-with(@class,"ta")]') #找到class属性里以ta开头的class
    # 取文本
    tree.xpath('//div[@class="song"]/p[1]/text()') #/text()获取当前标签下的直系储存的文本数据
    tree.xpath('//div[@class="tang"]//text()')    # # //text()获取某一个标签下所有子标签中存储的文本数据
    
    # 取属性
    tree.xpath('//div[@class="tang"]//li[2]/a/@href')
    • xpath插件:可以直接将xpath表达式作用于浏览器的网页当中
    • 安装: 更多工具—》扩展程序—》开启右上角开发者模式—》xpath插件拖动到页面即可
    • 快捷键: 开启和关闭xpath插件:可以自己定制 Ctrl+shift+s

    需求: 使用xpath对段子网中的段子内容和标题进行解析,持久化存储

    import requests
    from lxml import etree
    
    #1. 指定url
    url = 'https://ishuo.cn/joke'
    #2. 发送请求
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
    }
    response = requests.get(url=url,headers=headers)
    #3. 获取页面内容
    page_text = response.text
    #4. 数据解析
    tree = etree.HTML(page_text)
    #获取所有li标签(段子和标题都在li标签中)
    li_list=tree.xpath('//div[@id="list"]/ul/li')
    ####注意:Element类型的对象可以继续调用xpath函数,对该对象表示的局部内容进行指定内容的解析 ########
    f = open('./duanzi.txt','w',encoding='utf8')
    for li in li_list:   #每个li对象都是Element类型
        content = li.xpath('./div[@class="content"]/text()')[0]
        title = li.xpath('./div[@class="info"]/a/text()')[0]
    #5. 持久化存储
        f.write(title+":"+content+"
    
    ")
        print('一条数据写入成功')

    Beautiful解析:

    - python独有,简单便捷高效
    - 代码使用流程:
        pip install bs4
        核心思想:将HTML文档转换成beautifulsoup对象,然后调用该对象中的属性和方法进行HTML文档指定内容的定位查找
        导包: from bs4 import BeautifulSoup
        创建BeautifulSoup对象:
            - 如果HTML文档的来源是本地:
            BeautifulSoup('open(本都的HTML文件)','lxml')
            - 如果HTML文档来源是网络:
            BeautifulSoup('网络请求到的页面数据','lxml')
    - 属性和方法:
        (1) 根据标签名查找
            - soup.a   只能找到第一个符合要求的标签
            - soup.div  只能找到第一个符合要求的标签
        (2)获取属性
            - soup.a.attrs  获取a所有的属性和属性值,返回一个字典
            - soup.a.attrs['href'] 获取href属性
            - soup.a['href']   获取href属性的简写,通常这么写 
        (3) 获取内容
            - soup.a.string  获取某个标签存储的直系的内容,相当于/text()
            - soup.a.text   获取某个标签下的所有内容,相当于xpath的//text()
            - soup.a.get_text() 获取某个标签下的所有内容,相当于xpath的//text()
            {注意}如果标签还有标签,那么string获取到的结果为None,而其他两个可以获取文本
         (4)find:找到第一个符合要求的标签,根据属性定位标签
             - soup.find('a') 找到第一个符合要求的
             - soup.find('a',title='xxx')
             - soup.find('a',alt='xxx')
             - soup.find('a',class_='xxx')   #注意class_后有下划线
             - soup.find('a',id='xxx')
         (5) find_All:找到所有符合要求的标签,返回的是列表    
             -soup.findAll('a')
             -soup.findAll(['a','b'])  找到所有的a和b标签
             -soup.findAll('a',limit=2) 限制前2个
         (6) 根据选择器选择指定的内容【select选择器返回的永远是列表。需通过下标取指定对象】
                 select用法 : soup.select('#feng')
             -常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器
                 -层级选择器:
                  1 >只能是下面一级:  soup.select('div > img')[0]  div下的所有儿子img标签
                  2 空格,可以是下面好多级 例如  soup.select('div li') 等于soup.select('div>ui>li')
    rom bs4 import BeautifulSoup
    
    fp=open('text.html')
    soup = BeautifulSoup(fp,'lxml')

    需求:爬取古诗文网中三国小说里的标题和内容

    import requests
    from bs4 import BeautifulSoup
    
    url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
    }
    def get_content(url):
        content_page = requests.get(url=url,headers=headers).text
        soup = BeautifulSoup(content_page,'lxml')
        content=soup.find('div',class_='chapter_content').text
        return content
    page_text = requests.get(url=url,headers=headers).text
    #数据解析
    soup = BeautifulSoup(page_text,'lxml')
    #a_list列表中存储的是一系列的a标签对象
    a_list = soup.select('.book-mulu > ul > li > a ')
    # type(a_list[0]) 返回bs4.element.Tag
    #注意:Tag类型的对象可以继续调用相应的解析属性和方法进行局部数据的解析
    f = open('sanguo.txt','w',encoding='utf8')
    for a in a_list:
        title = a.string
        content_url = 'http://www.shicimingju.com' + a['href']
        content = get_content(content_url)
        f.write(title+":"+content+"/n/n/n")
        print('写入一个章节')
        
    - 需求:使用正则对糗事百科中的图片数据进行解析和下载
    import requests
    import re,os
    #指定url
    
    url = 'https://www.qiushibaike.com/pic/'
    
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
    }
    
    page_text = requests.get(url=url,headers=headers).text
    
    #数据解析(img_list中储存的就是当前页面源码中所有的图片链接)
    
    # img_list = re.findall('<div class="thumb">.*?<img src="(.*?)".*?>.*?</div>',page_text,re.S)
    img_list = re.findall('<div class="thumb">.*?<img src="(.*?)".*?</div>',page_text,re.S)
    
    #创建一个存储数据的文件夹
    
    if not os.path.exists('./qiubai_img'):
        os.mkdir('qiubai_img')
    
    for url in img_list:
        #将图片的url进行拼接,拼成完整的url
        img_url = 'https:'+ url
        #持久化存储:存储的是图片数据,不是url
        #获取图片的二进制数据
        img_data = requests.get(url=img_url,headers=headers).content
    #     print(img_data)
        imgName = img_url.split('/')[-1]
    #     print(imgName)
        imgPath = 'qiubai_img/'+ imgName
        print(imgPath)
        with open(imgPath,'wb') as f:
            f.write(img_data)
            print(imgName+'写入成功')

  • 相关阅读:
    MIPS、ARM、X86三大架构 (待写)
    NDIS驱动(待补充)
    iptables参数详解
    SSL协议详解
    shell脚本自学系列(3):shell编程基本语法简介
    shell脚本自学系列(x):十三个写好shell脚本的技巧分享
    软件质量模型的6大特性和27个子特性
    spring boot 热部署
    mysql 查询表死锁 和结束死锁的表步骤以及锁表等级
    高cpu分析
  • 原文地址:https://www.cnblogs.com/lys666/p/10478497.html
Copyright © 2011-2022 走看看