• 正则解析


    回顾

    • 问题:
      • ip被封:代理
      • 请求参数问题:
        • 动态变化的请求参数
        • 加密的请求参数
      • 响应数据的问题:
        • cookie
        • 请求参数
      • 加密:
        • js逆向
    • 重点内容
      • 参数的动态化
        • data/prames
      • 反爬机制:
        • robots.txt
        • UA检测
        • 动态加载的数据
          • 如何检测数据是否为动态加载
          • 如何捕获动态加载的数据
        • 动态加载的数据是如何生成?
          • ajax
          • js

    数据解析

    • 作用:实现聚焦爬虫
    • 实现方式:
      • 正则
      • bs4:重点
      • xpath:重点
      • pyquery:自学
    • 数据解析的通用原理是什么?
      • 解析的一定是html页面的源码数据
        • 标签中存储的文本内容
        • 标签属性的属性值
          • 原理:
          • 标签定位
          • 取文本或者取属性
    • 爬虫实现的流程
      • 指定url
      • 发请求
      • 获取响应数据
      • 数据解析
      • 持久化存储

    In [2]:

    import requests
    import re
    headers = {
        #需要修改的请求头信息
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
    }
    

    正则解析

    单字符: . : 除换行以外所有字符 [] :[aoe] [a-w] 匹配集合中任意一个字符 d :数字 [0-9] D : 非数字 w :数字、字母、下划线、中文 W : 非w s :所有的空白字符包,括空格、制表符、换页符等等。等价于 [ f v]。 S : 非空白 数量修饰:

        * : 任意多次  >=0
        + : 至少1次   >=1
        ? : 可有可无  0次或者1次
        {m} :固定m次 hello{3,}
        {m,} :至少m次
        {m,n} :m-n次
    边界:
        $ : 以某某结尾 
        ^ : 以某某开头
    分组:
        (ab)  
    贪婪模式: .*
    非贪婪(惰性)模式: .*?
    
    re.I : 忽略大小写
    re.M :多行匹配
    re.S :单行匹配
    
    re.sub(正则表达式, 替换内容, 字符串)
    

    In [ ]:

    import re
    #提取出python
    key="javapythonc++php"
    #####################################################################
    #提取出hello world
    key="<html><h1>hello world<h1></html>"
    #####################################################################
    #提取170
    string = '我喜欢身高为170的女孩'
    #####################################################################
    #提取出http://和https://
    key='http://www.baidu.com and https://boob.com'
    #####################################################################
    #提取出hit. 
    key='bobo@hit.edu.com'#想要匹配到hit.
    #####################################################################
    #匹配sas和saas
    key='saas and sas and saaas'
    #####################################################################
    

    In [3]:

    key="javapythonc++php"
    re.findall('python',key)
    

    Out[3]:

    ['python']
    

    In [4]:

    #提取出hello world
    key="<html><h1>hello world<h1></html>"
    re.findall('<h1>(.*?)<h1>',key)
    

    Out[4]:

    ['hello world']
    

    In [6]:

    #提取170
    string = '我喜欢身高为170的女孩'
    re.findall('d+',string)
    

    Out[6]:

    ['170']
    
    

    In [11]:

    #提取出http://和https://
    key='http://www.baidu.com and https://boob.com'
    re.findall('https?://',key)
    
    

    Out[11]:

    ['http://', 'https://']
    
    

    In [13]:

    #提取出hit. 
    key='bobo@hit.edu.com'#想要匹配到hit.
    re.findall('h.*?.',key)
    
    

    Out[13]:

    ['hit.']
    
    

    In [14]:

    #匹配sas和saas
    key='saas and sas and saaas'
    re.findall('sa{1,2}s',key)
    
    

    Out[14]:

    ['saas', 'sas']
    
    

    In [16]:

    url = 'http://duanziwang.com/category/搞笑图/'
    #捕获到的是字符串形式的响应数据
    page_text = requests.get(url=url,headers=headers).text
    
    #数据解析
    ex = '<div class="post-head">.*?<a href="http://duanziwang.com/d+.html">(.*?)</a></h1>'
    re.findall(ex,page_text,re.S)#爬虫使用正则做解析的话re.S必须要使用
    
    #持久化存储
    
    

    Out[16]:

    ['比较下老婆和老妈,一比吓一跳_段子网收录最新段子',
     '搞笑夫妻:烦恼里面找快乐_段子网收录最新段子',
     '夫妻界的搞笑奇葩_段子网收录最新段子',
     '超囧冷人小夫妻_段子网收录最新段子',
     '雷人夫妻:吃泡面、偷看日记和生日送花_段子网收录最新段子',
     '脸皮薄的人难以成功_段子网收录最新段子',
     '12秒的雷政富和21秒李小璐_段子网收录最新段子',
     '从前有只麋鹿,它在森林里玩儿,不小心走丢了。于是它给它的好朋友长颈鹿打电话:“喂…我迷路啦。”长颈鹿听见了回答说:“喂~我长颈鹿啦~”_段子网收录最新段子',
     '最萌挡车球_段子网收录最新段子',
     '再高贵冷艳的喵星人! 也总有一天有被吓得屁滚尿流的时候。_段子网收录最新段子']
    
    

    bs4解析

    • 环境安装:

      • pip install bs4
      • pip install lxml
    • 解析原理

      • 1.实例化一个BeautifulSoup的对象,需要将等待被解析的页面源码数据加载到该对象中
      • 2.需要调用BeautifulSoup对象中相关的属性和方法进行标签定位和文本数据的提取
    • BeautifulSoup如何实例化

      • 方式1:BeautifulSoup(fp,'lxml'),将本地存储的一张html文件中的指定数据进行解析
      • 方式2:BeautifulSoup(page_text,'lxml'),将从互联网中爬取到的数据直接进行数据解析
    • 标签定位

      • soup.tagName:定位到第一个出现的tagName标签
      • 属性定位:根据指定的属性进行对应标签的定位
        • soup.find('tagName',attrName='value')
        • soup.find_all('tagName',attrName='value')
      • 选择器定位:
        • soup.select('选择器')
        • 层级选择器:
          • 大于号:表示一个层级
          • 空格:表示多个层级
    • 取文本

      • tag.string:取出直系的文本内容
      • tag.text:取出所有的文本内容
    • 取属性

      • tag['attrName']

    In [18]:

    from bs4 import BeautifulSoup
    fp = open('./test.html','r',encoding='utf-8')
    soup = BeautifulSoup(fp,'lxml')
    soup
    
    

    . . .

    In [28]:

    soup.div
    # soup.find('div',class_='song')
    # soup.find('a',id='feng')
    # soup.find_all('div',class_='song')
    # soup.select('.tang')
    # soup.select('#feng')
    soup.select('.tang li')
    
    

    . . .

    In [38]:

    soup.p.string
    soup.p.text
    soup.find('div',class_='tang').text
    a_tag = soup.select('#feng')[0]
    a_tag['href']
    
    

    Out[38]:

    'http://www.haha.com'
    
    

    In [44]:

    main_url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
    page_text = requests.get(url=main_url,headers=headers).text
    
    fp = open('./sanguo.txt','w',encoding='utf-8')
    
    #数据解析
    soup = BeautifulSoup(page_text,'lxml')
    #解析出章节的标题&详情页的url
    a_list = soup.select('.book-mulu > ul > li > a')
    for a in a_list:
        title = a.string
        detail_url = 'http://www.shicimingju.com'+a['href']
        
        #捕获章节内容
        page_text_detail = requests.get(detail_url,headers=headers).text#获取了详情页的页面源码数据
        #数据解析:章节内容
        detail_soup = BeautifulSoup(page_text_detail,'lxml')
        div_tag = detail_soup.find('div',class_='chapter_content')
    
        content = div_tag.text
        
        fp.write(title+':'+content+'
    ')
        print(title,'下载成功!!!')
    fp.close()
    
    

    . . .

    • 图片数据的爬取
      • 基于requests
      • 基于urllib
      • 区别:能不能实现UA伪装

    In [47]:

    #基于requests
    url = 'http://pic.netbian.com/uploads/allimg/190902/152344-1567409024af8c.jpg'
    img_data = requests.get(url=url,headers=headers).content#content返回的是二进制类型的数据
    with open('./123.png','wb') as fp:
        fp.write(img_data)
    
    

    In [49]:

    #基于urllib
    from urllib import request
    request.urlretrieve(url=url,filename='./456.jpg')
    
    

    Out[49]:

    ('./456.jpg', <http.client.HTTPMessage at 0x217a8af3470>)
    
    

    xpath解析

    • 环境安装:
      • pip install lxml
    • 解析原理
      • 实例化一个etree的对象,且将被解析的页面源码数据加载到该对象中
      • 使用etree对象中的xpath方法结合着不同形式的xpath表达式进行标签定位和数据的提取
    • 实例化对象:
      • etree.parse('filePath'):将本地存储的一个html文件中的数据加载到实例化好的etree对象中
      • etree.HTML(page_text)
    • xpath表达式
      • 标签定位:
        • 最左侧的/:必须从根节点开始定位标签(几乎不用)
        • 非最左侧的/:表示一个层级
        • 最左侧的//:可以从任意位置进行指定标签的定位(最常用)
        • 非最左侧的//:表示多个层级
        • 属性定位://tagName[@attrName="value"]
        • 索引定位://tagNamne[index],索引是从1开始
        • //div[contains(@class, "ng")]
        • //div[starts-with(@class, "ta")]
      • 取文本
        • /text():取出直系的文本内容
        • //text():取出的是所有的文本
      • 取属性
        • /@attrName

    In [76]:

    from lxml import etree
    tree = etree.parse('./test.html')
    tree.xpath('/html/head/meta')
    tree.xpath('/html//meta')
    tree.xpath('//meta')
    tree.xpath('/meta')#error
    tree.xpath('//p')
    tree.xpath('//div[@class="tang"]')
    tree.xpath('//li[1]')
    tree.xpath('//a[@id="feng"]/text()')[0]
    tree.xpath('//div[@class="tang"]//text()')
    tree.xpath('//a[@id="feng"]/@href')
    
    

    Out[76]:

    ['http://www.haha.com']
    
    

    重点:局部解析的时候./表示的含义

    In [86]:

    import os
    
    

    In [88]:

    url = 'http://pic.netbian.com/4kmeinv/'
    page_text = requests.get(url=url,headers=headers).text
    
    dirName = 'imgLibs'
    if not os.path.exists(dirName):
        os.mkdir(dirName)
    
    #数据解析
    tree = etree.HTML(page_text)
    #xpath是基于一整张页面源码进行数据解析
    img_list = tree.xpath('//div[@class="slist"]/ul/li/a/img')
    
    #局部数据解析
    for img in img_list:
        #./表示的是当前标签,xpath的调用者就是当前标签
        img_src = 'http://pic.netbian.com'+img.xpath('./@src')[0]
        img_name = img.xpath('./@alt')[0]+'.jpg'
        img_name = img_name.encode('iso-8859-1').decode('gbk')
        
        filePath = './'+dirName+'/'+img_name
        request.urlretrieve(img_src,filename=filePath)
        print(img_name,'下载成功!!!')
    
    

    . . .

    In [90]:

    #全站操作
    #1.指定一个通用的url模板:用来生成不同页码对应的url,模板是不可变
    url = 'http://pic.netbian.com/4kmeinv/index_%d.html'
    dirName = 'imgLibs'
    if not os.path.exists(dirName):
        os.mkdir(dirName)
        
    for pageNum in range(1,6):
        if pageNum == 1:
            page_url = 'http://pic.netbian.com/4kmeinv/'
        else:
            page_url = format(url%pageNum)
    
        page_text = requests.get(url=page_url,headers=headers).text
    
        #数据解析
        tree = etree.HTML(page_text)
        #xpath是基于一整张页面源码进行数据解析
        img_list = tree.xpath('//div[@class="slist"]/ul/li/a/img')
    
        #局部数据解析
        for img in img_list:
            #./表示的是当前标签,xpath的调用者就是当前标签
            img_src = 'http://pic.netbian.com'+img.xpath('./@src')[0]
            img_name = img.xpath('./@alt')[0]+'.jpg'
            img_name = img_name.encode('iso-8859-1').decode('gbk')
    
            filePath = './'+dirName+'/'+img_name
            request.urlretrieve(img_src,filename=filePath)
            print(img_name,'下载成功!!!')
    
    

    . . .

    In [ ]:

    python
  • 相关阅读:
    纸壳CMS替换默认实现
    ASP.Net Core 2.2 InProcess托管的Bug:unable to open database file
    GitHub设置使用SSH Key,用TortoiseGit进行Clone仓库
    在Docker中运行纸壳CMS并配置使用MySql
    使用vs code开发纸壳CMS并启用Razor智能提示
    ASP .Net Core路由(Route)
    .Net Core在Middleware中解析RouteData
    纸壳CMS可视化建站系统搭建多语言网站
    Redis的初识
    C#/Java 动态生成电子发票
  • 原文地址:https://www.cnblogs.com/bky20061005/p/12145691.html
Copyright © 2020-2023  润新知