Python成长之路——regex,bs4,xpath,jsonpath的使用

本文介绍了Python中用于网页解析的四个关键工具:正则表达式regex、BeautifulSoup库bs4、XPath以及JsonPath。讲解了它们的基本用法,如regex的匹配规则,bs4的标签选择和属性获取,XPath的路径表达式,以及JsonPath在解析JSON数据中的应用。同时,提到了BeautifulSoup需要配合lxml库使用,并展示了如何在Python中安装和使用这些工具。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Regular Expression(正则表达式)
  • 正则表达式解析

    模式描述
    ^匹配字符串的开头
    $匹配字符串的末尾。
    .匹配任意字符,除了换行符,。[…] 用来表示一组字符,单独列出:[amk] 匹配 ‘a’,‘m’或’k’
    [^…]不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
    re*匹配0个或多个的表达式。
    re+匹配1个或多个的表达式。
    re?匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
    re{ n}
    re{ n,}精确匹配n个前面表达式。
    re{ n, m}匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
    ab
    (re)G匹配括号内的表达式,也表示一个组
    (?imx)正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
    (?-imx)正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
    (?: re)类似 (…), 但是不表示一个组
    (?imx: re)在括号中使用i, m, 或 x 可选标志
    (?-imx: re)在括号中不使用i, m, 或 x 可选标志
    (?#…)注释.
    (?! re)前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功
    (?> re)匹配的独立模式,省去回溯。
    \w匹配字母数字
    \W匹配非字母数字
    \s匹配任意空白字符,等价于 [\t\n\r\f].
    \S匹配任意非空字符
    \d匹配任意数字,等价于 [0-9].
    \D匹配任意非数字
    \A匹配字符串开始
    \Z匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串
    \z匹配字符串结束
    \G匹配最后匹配完成的位置。
    \b匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。
    \B匹配非单词边界。‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。
    \n, \t, 等.匹配一个换行符。匹配一个制表符。等
    \1…\9匹配第n个分组的子表达式。
    \10匹配第n个分组的子表达式,如果它经匹配。否则指的是八进制字符码的表达式。
    贪婪模式类型说明
    .*?. 是任意字符,* 是取 0 至 无限长度,? 是非贪婪模式。合在一起就是 取尽量少的任意字符
    .+?前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配
    修饰符说明
    re.I忽略大小写
    re.M多行匹配
    re.S单行匹配
    re.L做本地化识别(locale-aware)匹配
    re.U根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
    re.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解
    re模块说明
    re.match从开始位置开始匹配,如果开头没有则无
    re.search搜索整个字符串
    re.findall搜索整个字符串,返回一个list

    r(raw)用在pattern之前,表示单引号中的字符串为原生字符,不会进行任何转义
    re.match(r’a’,‘abcd1’).group() #返回l
    re.match(r’g’,‘bdgf1’) #返回None
    re.search(r’b’,‘abcd1’).group() #返回y
    group()用来提出分组截获的字符串,()用来分组

bs4(beautifulsoup)
  • 将pip安装源切换到国内

    1、 打开资源文件管理器
    2.、在地址栏输入%appdata%
    3、在这里面新建一个文件夹pip
    4、 在pip文件夹里面新建一个文件叫做pip.ini,内容写如下即可

    [global]
    	timeout = 6000
    	index-url = https://mirrors.aliyun.com/pypi/simple/
    	trusted-host = mirrors.aliyun.com
    
  • 需要安装:pip install bs4

    bs4在使用时候需要一个第三方库,把这个库也安装一下 pip install lxml
    简单使用:
    说明:选择器,jquery
    from bs4 import BeautifulSoup
    使用方式:可以将一个html文档,转化为指定的对象。然后通过对象的方法或者属性去查找指定的内容
    -。转化本地文件
    soup = BeautifulSoup(open(“本地文件”,encoding=""),“lxml”)
    -。转化网络文件
    soup = BeautifulSoup(open(“字符串类型或者是字节类型”),“lxml”)

  • (1)根据标签名查找

    soup.a 只能找到第一个标签

  • (2)获取属性

    soup.a.attrs 获取所有属性和值,返回一个字典
    soup.a.attrs[‘href’] 获取href属性
    soup.a[‘href’] 也可以简写这种形式

  • (3)获取内容

    soup.a.text
    soup.a.string
    soup.a.get_text()
    如果标签里面还有标签,那么string获取到的结果为None,而其他两个,可以获取文本内容

  • (4)find

    soup.find(‘a’) 找到第一个符合要求的a
    soup.find(‘a’,title=“xxx”)
    soup.find(‘a’,alt=“xx”)
    soup.find(‘a’,class_=“xxx”)
    soup.find(‘a’,id=“xxx”)
    find方法不仅soup可以调用,普通的div对象也能调用,会去指定的div里面去查找符合要求的节点
    find找到的都是符合要求的第一个标签

  • (5)find_all

    soup.find_all(‘a’)
    soup.find_all([‘a’,‘b’])
    soup.find_all(‘a’,limit=2) 限制前两个

  • (6)select

    根据选择器选择指定的内容
    常见的选择器:
    标签选择器:a
    类选择器: .class
    id选择器: #id
    并集选择器:a,.class,#id
    组合选择器:div .class #id
    层级选择器:div>p>a
    伪类选择器:
    属性选择器:input[name=‘name’]
    select选择器返回永远是列表,需要通过下标提取指定的对象,然后获取属性和节点
    该方法也可以通过普通对象调用,找到都是这个对象下面符合要求的所有节点

xpath
  • 什么是xpath?

    xpath用来在xml中查找指定的元素,它是哟中路径表达式
    常用的路径表达式:
    / 从根节点选取(直接子节点,如果是孙子节点的话就会获取不到)
    // 从匹配选择的当前节点选择文档中的节点,而不是考虑它们的位置
    . 选取当前的节点
    … 选取当前节点的父节点
    @ 选取属性

  • 安装xpath插件

    将xpath插件拖动到谷歌浏览器扩展程序中,安装成功
    启动和关闭插件
    ctrl + shift + x

  • 使用方式

    属性定位://input[@id=‘kw’]
    层级定位://div/div/a
    索引定位://div[@id=‘head’]/div/div[2]/a[1]
    逻辑运算://input[@class=‘s_ipt’ and #name=‘name’]
    模糊匹配://input[contains(@class,‘s_i’)];//input[starts-with(@class,‘s’)]
    取文本://div[@id=u1]/a[5]/text()
    取属性://div[@id=u1]/a[5]/@href

  • 代码中使用xpath

    第一种引入方式:from lxml import etree
    第二种引入方式:from lxml import html;etree = html.etree
    两种方式使用:将html文档变成一个对象,然后调用对象的方法去查找指定的节点
    1、本地文件
    tree = etree.parse(文件名)
    2、网络文件
    tree = etree.HTML(网络中的字符串)
    3、ret = tree.xpath(路径表达式)
    ret返回的是一个列表

图片懒加载

懒加载技术:用到的时候再加载

实现方式:
"<img src2="图片路径">"	当页面加载时,图片还没有出现在用户眼前时
<img src="图片路径" src2="">	当图片出现在用户眼前时,js就会动态的在img标签上加上一个src属性,并将src2上的路径添加到src上,就会发送请求,将图片显示出来

os.path.basename(image_src):获取图片链接中的图片名
os.path.join(dirname,filename):将路径与文件名进行拼接
爬取素材网的图片

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : xingganmeinvtupian.py
# @Author: changqi
# @Date  : 2019/4/20
# @Desc  :

from urllib import request,parse
from lxml import html
import time,os
etree = html.etree

def handle_request(url,page):
    if (page == 1):
        url = url.format("")
    else:
        url = url.format("_" + str(page))
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"}
    request_url = request.Request(url=url, headers=headers)
    return request_url

def parse_content(content):
    tree = etree.HTML(content)
    image_list = tree.xpath("//div[@id='container']/div/div/a/img/@src2")
    for image_src in image_list:
        download_image(image_src)

def download_image(image_src):
    dirname = "xgmn"
    if not os.path.exists(dirname):
        os.mkdir(dirname)
    picname = os.path.basename(image_src)
    filepath = os.path.join(dirname,picname)
    print("%s 图片下载开始..."%picname)
    request.urlretrieve(image_src,filepath)
    print("%s 图片下载结束..."%picname)

def main():
    start_page = int(input("请输入起始页码:"))
    end_page = int(input("请输入结束页码:"))
    url = "http://sc.chinaz.com/tupian/xingganmeinvtupian{}.html"
    for page in range(start_page,end_page + 1):
        print("%s 第一页开始下载..." % page)
        request_url = handle_request(url,page)
        content = request.urlopen(request_url).read().decode()
        parse_content(content)
        time.sleep(2)
        print("%s 第一页下载结束..." % page)

if __name__ == "__main__":
    main()
jsonpath

用来解析json数据使用,Python处理json格式用到的函数

import json
json.dumps()	将字典或者列表转化为json格式的字符串
json.dump()	将字典或者列表转化为json格式的字符串并且写入到文件中
json.loads()	将json格式的字符串转化为python对象
json.load()	从文件中读取json格式字符串,转化为python对象

前端处理

将json格式字符串转为js对象
JSON.parse(‘json格式字符串’)
eval(’(’ + json格式字符串 + ‘)’)

以下jsonpath来自:http://goessner.net/articles/JsonPath/

  • JSONPath - 是xpath在json的应用。
    xml最大的优点就有大量的工具可以分析,转换,和选择性的提取文档中的数据。XPath是这些最强大的工具之一。
    如果可以使用xpath来解析json,以下的问题可以被解决:
    1,数据不使用特殊的脚本,可以在客户端交互的发现并取并获取。
    2,客户机请求的JSON数据可以减少到服务器上的相关部分,这样可以最大限度地减少服务器响应的带宽使用率。
    如果我们愿意,这个可以解析json数据的工具会变得有意义。随之而来的问题是它如何工作,jsonpath的表达式看起来怎么样。
    事实上,json是由c系统编程语言表示自然数据,有特定语言的特定语法来访问json数据。
    xpath的表达式:
    /store/book[1]/title
    我们可以看作是:
    x.store.book[0].title

    x[‘store’][‘book’][0][‘title’]
    在Javascript, Python 和 PHP 中一个变量x表示json数据。经过观察,特定的语言里有内置xpath来解析数据。

  • JSONPath 表达式
    JSONPath 是参照,xpath表达式来解析xml文档的方式,json数据结构通常是匿名的并且不一定需要有根元素。JSONPaht 用一个抽象的名字$来表示最外层对象。
    JOSNPath 表达式可以使用. 符号如下:
    $.store.book[0].title
    或者使用[] 符号
    $[‘store’][‘book’][0][‘title’]
    从输入路径来看。内部或者输出的路径都会转化成-符号。
    JSONPath 允许使用通配符 * 表示所以的子元素名和数组索引。还允许使用 ‘…’ 从E4X参照过来的和数组切分语法[start?step]是从ECMASCRIPT 4 参照过来的。
    表达式在下面的脚本语言中可以使用显示的名称或者索引:
    $.store.book[(@.length-1)].title
    使用’@'符号表示当前的对象,?(<判断表达式>) 使用逻辑表达式来过滤。
    $.store.book[?(@.price < 10)].title

    XPathJSONPathDescription
    /$表示根元素
    .@当前元素
    /. or []子元素
    n/a父元素
    //递归下降,JSONPath是从E4X借鉴的。
    **通配符,表示所有的元素
    @n/a属性访问字符
    [][]子元素操作符
    |[,]连接操作符在XPath 结果合并其它结点集合。JSONP允许name或者数组索引。
    n/a[start?step]数组分割操作从ES4借鉴。
    []?()应用过滤表示式
    n/a()脚本表达式,使用在脚本引擎下面。
    ()n/aXpath分组

    []在xpath表达式总是从前面的路径来操作数组,索引是从1开始。
    使用JOSNPath的[]操作符操作一个对象或者数组,索引是从0开始。

    jsonPath 例子

    { "store": {
        "book": [ 
          { "category": "reference",
            "author": "Nigel Rees",
            "title": "Sayings of the Century",
            "price": 8.95
          },
          { "category": "fiction",
            "author": "Evelyn Waugh",
            "title": "Sword of Honour",
            "price": 12.99
          },
          { "category": "fiction",
            "author": "Herman Melville",
            "title": "Moby Dick",
            "isbn": "0-553-21311-3",
            "price": 8.99
          },
          { "category": "fiction",
            "author": "J. R. R. Tolkien",
            "title": "The Lord of the Rings",
            "isbn": "0-395-19395-8",
            "price": 22.99
          }
        ],
        "bicycle": {
          "color": "red",
          "price": 19.95
        }
      }
    }
    
    XPathJSONPath结果
    /store/book/author$.store.book[*].author书点所有书的作者
    //author$…author所有的作者
    /store/*$.store.*store的所有元素。所有的bookst和bicycle
    /store//price$.store…pricestore里面所有东西的price
    //book[3]$…book[2]第三个书
    //book[last()]$…book[(@.length-1)] 最后一本书
    //book[position()<3]$…book[0,1] $…book[:2]前面的两本书。
    //book[isbn]$…book[?(@.isbn)]过滤出所有的包含isbn的书。
    //book[price<10]$…book[?(@.price<10)]过滤出价格低于10的书。
    //*$…*所有元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值