首页 > 其他分享 >爬虫之xpath的使用

爬虫之xpath的使用

时间:2024-04-02 13:22:22浏览次数:20  
标签:xpath img text 爬虫 li 标签 使用 div

一、xpath初步认识

1、xpath介绍

XPath(XML Path Language)是一种用于在 XML 文档中定位节点的语言。它是一种在 XML 文档中导航和查询信息的语言,类似于在关系数据库中使用 SQL 查询数据。XPath 提供了一种灵活的方式来定位和处理 XML 文档中的元素和属性。

2、lxml的安装

lxml是Python的一个第三方解析库,支持HTML和XML解析,而且效率非常高,弥补了Python自带的xml标准库在XML解析方面的不足。

由于是第三方库,所以在使用 lxml 之前需要先安装:pip install lxml

from lxml import etree

# 将源码转化为能被XPath匹配的格式
selector=etree.HTML(源码) 

# 返回为一列表
selector.xpath(表达式) 

3、xpath解析原理

XPath 使用路径表达式来选取 XML 文档中的节点或节点集。这些路径表达式类似于文件系统中的路径,可以沿着元素和属性之间的层次结构前进,并选择所需的节点。XPath 也支持使用谓词来过滤和选择节点,以便更精确地定位目标节点。

二、xpath的语法

XPath 语法 : XPath 参考手册 ] - 在线原生手册 - php中文网

1、选取节点

表达式 描述
nodename 选取此节点的所有子节点。
/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。

在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:

路径表达式 结果
bookstore 选取 bookstore 元素的所有子节点。
/bookstore 选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book 选取属于 bookstore 的子元素的所有 book 元素。
//book 选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//@lang 选取名为 lang 的所有属性。

2、谓语

谓语用来查找某个特定的节点或者包含某个指定的值的节点。

谓语被嵌在方括号中。

在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:

路径表达式 结果
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()❤️] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang] 选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang='eng'] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

3、选取未知节点

XPath 通配符可用来选取未知的 XML 元素。

通配符 描述
* 匹配任何元素节点。
@* 匹配任何属性节点。
node() 匹配任何类型的节点。

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式 结果
/bookstore/* 选取 bookstore 元素的所有子元素。
//* 选取文档中的所有元素。
//title[@*] 选取所有带有属性的 title 元素。

4、选取若干路径

通过在路径表达式中使用"|"运算符,您可以选取若干个路径。

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式 结果
//book/title | //book/price 选取 book 元素的所有 title 和 price 元素。
//title | //price 选取文档中的所有 title 和 price 元素。
/bookstore/book/title | //price 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

(1)逻辑运算

//div[@id="head" and @class="s_down"] # 查找所有id属性等于head并且class属性等于s_down的div标签
//title | //price # 选取文档中的所有 title 和 price 元素,“|”两边必须是完整的xpath路径

(2)属性查询

//div[@id] # 找所有包含id属性的div节点
//div[@id="maincontent"]  # 查找所有id属性等于maincontent的div标签
//@class
//li[@name="xx"]//text()  # 获取li标签name为xx的里面的文本内容

(3)获取第几个标签 索引从1开始

tree.xpath('//li[1]/a/text()')  # 获取第一个
tree.xpath('//li[last()]/a/text()')  # 获取最后一个
tree.xpath('//li[last()-1]/a/text()')  # 获取倒数第二个

(4)模糊查询

//div[contains(@id, "he")]  # 查询所有id属性中包含he的div标签
//div[starts-with(@id, "he")] # 查询所有id属性中包以he开头的div标签

//div/h1/text()  # 查找所有div标签下的直接子节点h1的内容
//div/a/@href   # 获取a里面的href属性值 
//*  #获取所有
//*[@class="xx"]  #获取所有class为xx的标签

# 获取节点内容转换成字符串
c = tree.xpath('//li/a')[0]
result=etree.tostring(c, encoding='utf-8')
print(result.decode('UTF-8'))

5、示例

from lxml import etree

doc = '''
<html>
 <head>
  <base href='http://example.com/' />  <!-- 设置基准链接 -->
  <title>Example website</title>  <!-- 设置网页标题 -->
 </head>
 <body>
  <div id='images'>
   <a href='image1.html' id='lqz'>Name: My image 1 <br /><img src='image1_thumb.jpg' /></a>
   <a href='image2.html'>Name: My image 2 <br /><img src='image2_thumb.jpg' /></a>
   <a href='image3.html'>Name: My image 3 <br /><img src='image3_thumb.jpg' /></a>
   <a href='image4.html'>Name: My image 4 <br /><img src='image4_thumb.jpg' /></a>
   <a href='image5.html' class='li li-item' name='items'>Name: My image 5 <br /><img src='image5_thumb.jpg' /></a>
   <a href='image6.html' name='items'><span><h5>test</h5></span>Name: My image 6 <br /><img src='image6_thumb.jpg' /></a>
  </div>
 </body>
</html>
'''

# 将HTML字符串转为可解析的对象
html = etree.HTML(doc)

# 1. 获取所有节点
all_nodes = html.xpath('//*')
print(all_nodes)

# 2. 指定节点(结果为列表)
head_node = html.xpath('//head')
print(head_node)

# 3. 子节点和子孙节点
child_nodes = html.xpath('//div/a')  # 获取div下的所有a标签
descendant_nodes = html.xpath('//body//a')  # 获取body下的所有子孙a标签
print(child_nodes)
print(descendant_nodes)

# 4. 父节点
parent_node = html.xpath('//body//a[1]/..')  # 获取第一个a标签的父节点
print(parent_node)

# 5. 属性匹配
matched_nodes = html.xpath('//body//a[@href="image1.html"]')  # 获取href属性为"image1.html"的a标签
print(matched_nodes)

# 6. 文本获取
text = html.xpath('//body//a[@href="image1.html"]/text()')  # 获取第一个a标签的文本内容
print(text)

# 7. 属性获取
href_attributes = html.xpath('//body//a/@href')  # 获取所有a标签的href属性值
print(href_attributes)

# 8. 属性多值匹配
li_class_nodes = html.xpath('//body//a[contains(@class, "li")]')  # 获取class属性包含"li"的a标签
print(li_class_nodes)

# 9. 多属性匹配
matched_nodes = html.xpath('//body//a[contains(@class, "li") and @name="items"]')  # 获取class属性包含"li"和name属性为"items"的a标签
print(matched_nodes)

# 10. 按序选择
second_a_text = html.xpath('//a[2]/text()')  # 获取第二个a标签的文本内容
print(second_a_text)

# 11. 节点轴选择
ancestors = html.xpath('//a/ancestor::*')  # 获取a标签的所有祖先节点
div_ancestor_node = html.xpath('//a/ancestor::div')  # 获取a标签的祖先节点中的div
attribute_values = html.xpath('//a[1]/attribute::*')  # 获取第一个a标签的所有属性值
child_nodes = html.xpath('//a[1]/child::*')  # 获取第一个a标签的所有子节点
descendant_nodes = html.xpath('//a[6]/descendant::*')  # 获取第六个a标签的所有子孙节点
following_nodes = html.xpath('//a[1]/following::*')  # 获取第一个a标签之后的所有节点
following_sibling_nodes = html.xpath('//a[1]/following-sibling::*')  # 获取第一个a标签之后的同级节点

print(ancestors)
print(div_ancestor_node)
print(attribute_values)
print(child_nodes)
print(descendant_nodes)
print(following_nodes)
print(following_sibling_nodes)

XPath 是一种强大的工具,广泛用于 XML 文档的处理和解析。它在各种领域中都有广泛的应用,包括 Web 开发、数据抓取、数据提取和数据转换等方面。在 Web 开发中,XPath 经常与 XML、HTML 和 XSLT(Extensible Stylesheet Language Transformations)一起使用,用于从网页中提取数据或进行数据转换。

三、项目实例

1、实例一

需求:
爬取58同城二手房源信息(以北京市为例)。解析出所有房源的名称,并进行持久化存储。
网址:https://bj.58.com/ershoufang/

思路:

主要就是观察页面的结构,看每个房源的名字所在的标签是哪个。然后写出xpath表达式即可。

import requests
from lxml import etree
from fake_useragent import UserAgent

url = 'https://bj.58.com/ershoufang/'
headers = {
    "User-Agent": UserAgent().random
}

# 爬取页面源码数据
page_text = requests.get(url=url, headers=headers).text

# 页面解析
tree = etree.HTML(page_text)
div_list = tree.xpath('//*[@id="esfMain"]/section/section[3]/section[1]/section[2]/div')
with open('58.txt', 'w',encoding='utf8') as f:
    for div in div_list:
        # 局部解析
        # 一定要加 . 这个 . 表示的就是局部定位到的标签
        title = div.xpath('./a/div[2]/div[1]/div[1]/h3')[0].text
        print(title)
        # 存入文件
        f.write(title + '\n')

2、案例二

需求:
爬取《红楼梦》所有章节的标题。
网址:https://www.shicimingju.com/book/hongloumeng.html

思路:

主要是对xpath表达式的书写。通过观察标签写出xpath表达式。

import requests
from lxml import etree
from fake_useragent import UserAgent

url = 'https://www.shicimingju.com/book/hongloumeng.html'
headers = {
    "User-Agent":UserAgent().random
}

page_text = requests.get(url=url,headers=headers).text

# 实例化etree对象
tree = etree.HTML(page_text)
li_list = tree.xpath('//*[@id="main_left"]/div/div[4]/ul/li')

with open('红楼梦.txt', 'w',encoding='utf8') as f:
    data_dic = []
    for li in li_list:
        title = li.xpath('./a/text()')[0]  # 获取标签里的文本值
        href = li.xpath('./a/@href')[0]  # 获取标签里的href值
        detail_url = 'https://www.shicimingju.com' + href
        detail_page_text = requests.get(url=detail_url,headers=headers)
        detail_page_text.encoding = 'utf8'
        detail_page_text = detail_page_text.text
        new_tree = etree.HTML(detail_page_text)
        # 文章内容
        p_list = new_tree.xpath('//*[@id="main_left"]/div[1]/div/p')
        for p in p_list:
            words = p.text
            print(words)
        data_dic.append({"title":title,"words":words})
    f.write(str(data_dic))

3、实例三

需求:
解析下载图片数据。
网址:https://pic.netbian.com/4kdongman/

思路:
主要是对 xpath表达式的书写,和怎样处理中文乱码。
xpath表达式可以从< div class = “slist”>标签开始,也可以从更上面的标签开始,比如< idv id = “main” > 可以从这里开始。
当然两个写法的含义是一样的。

import requests
from lxml import etree
from fake_useragent import UserAgent
import os

if __name__ == '__main__':
    url = 'https://pic.netbian.com/4kdongman/'
    header = {
        'User-Agent': UserAgent().random
    }
    # 爬取页面源码数据 获取相应对象
    reponse = requests.get(url=url, headers=header)
    # 手动设置响应数据编码格式
    # reponse.encoding = 'utf-8'
    page_text = reponse.text
    # 数据解析,解析src的属性值,解析alt的属性值
    # 实例化etree
    tree = etree.HTML(page_text)
    # xpath表达式
    # src_list = tree.xpath('//div[@id="main"]/div[3]/ul/li/a/img/@src')
    # alt_list = tree.xpath('//div[@id="main"]/div[3]/ul/li/a/img/@alt')
    # 也可以这样写
    src_list = tree.xpath('//div[@class="slist"]/ul/li')

    # 创建一个文件夹
    if not os.path.exists('./tupian'):
        os.mkdir('./tupian')

    for li in src_list:
        img_src = 'http://pic.netbian.com' + li.xpath('./a/img/@src')[0]
        img_alt = li.xpath('./a/img/@alt')[0] + '.jpg'
        # 统用处理解决中文乱码的解决方法
        img_alt = img_alt.encode('iso-8859-1').decode('gbk')
        print(img_alt + " : " + img_src)
        # 图片地址转化成二进制
        img_data = requests.get(url=img_src, headers=header).content
        img_path = './tupian/' + img_alt
        # 存储
        with open(img_path, 'wb') as fp:
            fp.write(img_data)

4、案例四

需求:
解析出所给网址中全国城市的名称。
网址:https://www.aqistudy.cn/historydata/

思路:

首先实例化xpath对象,然后根据热门城市和全部城市的标签层级关系写出xpath表达式。解析表达式所对应的a标签,然后xpath函数返回一个列表,列表中存的就是a标签对应的城市。然后我们遍历列表即可。

第一种写法:分别解析热门城市和所有城市,然后把这些城市的名字存入列表中。

import requests
from lxml import etree
import os
from fake_useragent import UserAgent

url = 'https://www.aqistudy.cn/historydata/'
headers = {
    'User-Agent':UserAgent().random
}

# 爬取页面源代码数据,获取响应对象
page_text = requests.get(url=url,headers=headers).text

# 数据解析
# 实例化对象
tree = etree.HTML(page_text)
all_city = []  # 所有的城市


# 热门城市
#  hot_city_list = tree.xpath('//div[@class="bottom"]/ul/li')
hot_city_list = tree.xpath('/html/body/div[3]/div/div[1]/div[1]/div[2]/ul/li')
for li in hot_city_list:
    hot_city_name = li.xpath('./a/text()')[0]
    all_city.append(hot_city_name)

all_city_list = tree.xpath('//div[@class="bottom"]/ul/div[2]/li')
for li in all_city_list:
    all_city_name = li.xpath('./a/text()')[0]
    all_city.append(all_city_name)

print(all_city,"一共有:",len(all_city),"个城市")

第二种写法:用按位或将两个层级关系连接。

我们无法只通过一共 xpath表达式,将两个层级标签都表示数量,但是我们可以将两个层级标签写在一起,只需要用按位或 “ | ” 进行分割。这个意味着将第一个 xpath表达式或者第二个 xpath表达式,作用到 xpath函数当中。这样可以解析第一个表达式所对应的a标签定位到,也可以将第二个表达式所对应的a标签定位到。

# 用按位或进行分割 “ | ”
a_city_list = tree.xpath('//div[@class="bottom"]/ul/li/a | //div[@class="bottom"]/ul/div[2]/li/a')

xpath返回一个列表,这个列表里面存的是热门城市加全部城市a标签所对应的一个列表。

然后遍历列表即可。


import requests
from lxml import etree

if __name__ == '__main__':
    url = 'https://www.aqistudy.cn/historydata/'
    header = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4209.2 Safari/537.36'
    }
    # 爬取页面源码数据 获取相应对象
    page_text = requests.get(url=url, headers=header).text

    # 数据解析
    # 实例化对象
    tree = etree.HTML(page_text)
    all_city = []  # 所有的城市
    # 解析到热门城市和所有城市对应的a标签
    # 热门城市对应a标签层级关系://div[@class="bottom"]/ul/li/a
    # 所有城市对应a标签层级关系://div[@class="bottom"]/ul/div[2]/li/a
    # 用按位或进行分割 “ | ”
    a_city_list = tree.xpath('//div[@class="bottom"]/ul/li/a | //div[@class="bottom"]/ul/div[2]/li/a')
    for a in a_city_list:
        city_name = a.xpath('./text()')[0]
        all_city.append(city_name)
    print(all_city, " 一共有:", len(all_city), "个城市")

5、案例五

需求:

获取大学生求职简历模板的封面和名称,并且打印下来。
网址:http://sc.chinaz.com/jianli/daxuesheng.html

思路:

首先实例化xpath对象,然后根据图片和名称的标签层级关系写出xpath表达式。解析表达式所对应的a标签,然后xpath函数返回一个列表,列表中存的就是a标签对应的图片和名字。然后我们遍历列表即可。

import requests
from fake_useragent import UserAgent
from lxml import etree

if __name__ == '__main__':
    header = {
        'User-Agent': UserAgent().random
    }

    # 第一页
    # 第一页的url和其它页的有所不同
    url1 = 'http://sc.chinaz.com/jianli/daxuesheng.html'
    # 爬取页面源码数据 获取相应对象
    reponse = requests.get(url=url1, headers=header)
    # 手动设置响应数据编码格式
    reponse.encoding = 'utf-8'
    page_text = reponse.text
    # 数据解析
    # 实例化对象
    tree = etree.HTML(page_text)
    src_list = tree.xpath('//div[@id="main"]/div/div')
    for a in src_list:
        img_src = a.xpath('./a/img/@src')[0]
        img_alt = a.xpath('./a/img/@alt')[0]
        # 统用处理解决中文乱码的解决方法
        # 会报错:UnicodeDecodeError: 'gbk' codec can't decode byte 0xbf in position 32: incomplete multibyte sequence
        # img_alt = img_alt.encode('iso-8859-1').decode('gbk')
        print(img_alt, ' : ', img_src)

    # 其他页(2到13页)
    url = 'http://sc.chinaz.com/jianli/daxuesheng'
    for num in range(2, 13 + 1):
        num = str(num)
        new_url = url + '_' + num + '.html'
        # 爬取页面源码数据 获取相应对象
        reponse = requests.get(url=new_url, headers=header)
        # 手动设置响应数据编码格式
        reponse.encoding = 'utf-8'
        page_text = reponse.text
        # 数据解析
        # 实例化对象
        tree = etree.HTML(page_text)
        src_list = tree.xpath('//div[@id="main"]/div/div')
        for a in src_list:
            img_src = a.xpath('./a/img/@src')[0]
            img_alt = a.xpath('./a/img/@alt')[0]
            # 统用处理解决中文乱码的解决方法
            # 会报错:UnicodeDecodeError: 'gbk' codec can't decode byte 0xbf in position 32: incomplete multibyte sequence
            # img_alt = img_alt.encode('iso-8859-1').decode('gbk')
            print(img_alt, ' : ', img_src)

具体流程:

当然我们发现每个模板的名字(中文信息)打印出来是乱码,这就需要我们更改编码格式。由于统用处理解决中文乱码的解决方法会报错,无法正常使用,所以我们使用手动设置响应数据编码格式。

reponse = requests.get(url=url,headers=header)
# 手动设置响应数据编码格式
reponse.encoding = 'utf-8'
page_text = reponse.text
  • 我们如何打印所有页的数据呢?
    • 我们观察发现,模板只有13页
  • 而网址也很相似:
第一页:http://sc.chinaz.com/jianli/daxuesheng.html
第二页:http://sc.chinaz.com/jianli/daxuesheng_2.html
第三页:http://sc.chinaz.com/jianli/daxuesheng_3.html
第四页:http://sc.chinaz.com/jianli/daxuesheng_4.html
...
第十三页:http://sc.chinaz.com/jianli/daxuesheng_13.html

我们观察发现除了第一页外其它12页的url只有后面的数字不同,我们可以用字符串拼接的方法将url拼接出来,而那个不同的数字用for循环即可,然后将循环变量强制转换成str型的,最后拼接字符串。而第一页的特殊处理,独立输出,其他页(2到13页)的循环输出。

四、乱码解决办法

解决方法一:

手动设置响应数据编码格式。

reponse = requests.get(url=url,headers=header)
# 手动设置响应数据编码格式
reponse.encoding = 'utf-8'
page_text = reponse.text

解决方法二:

找到发生乱码对应的数据,对该数据进行:encode(‘iso-8859-1’).decode(‘gbk’) 操作。

# 统用处理解决中文乱码的解决方法
img_alt = img_alt.encode('iso-8859-1').decode('gbk')

案例三和案例五就是对这两种处理中文乱码的方法的应用。
案例三:是方法二。统用处理解决中文乱码的解决方法。
案例五:是方法一。手动设置响应数据编码格式。

标签:xpath,img,text,爬虫,li,标签,使用,div
From: https://www.cnblogs.com/xiao01/p/18110367

相关文章

  • 腾讯云优惠券领取方法、领券页面及使用教程
    随着云计算技术的不断发展,越来越多的企业和个人选择将业务迁移到云平台上。腾讯云作为国内领先的云计算服务提供商,为用户提供了稳定、高效、安全的云服务。为了吸引用户上云,腾讯云经常推出各种优惠活动,其中就包括发放腾讯云优惠券。本文将详细介绍腾讯云优惠券的领取方法、领券......
  • [实验室服务器使用]使用VSCode、PyCharm、MobaXterm和CMD连接远程服务器
    实验室服务器使用:使用VSCode、PyCharm、MobaXterm和CMD连接远程服务器在进行实验室工作时,远程连接服务器是常见的需求之一。本篇文章根据个人的一些使用介绍使用不同工具连接服务器的方法,并提供优化功能,使服务器能够使用本机代理的说明。准备服务器账号信息Host(主机):10.......
  • ELK介绍与Spring Boot集成使用
    ELK介绍与SpringBoot集成使用LogstashLogstash是一个具有实时管道功能的开源数据收集引擎。Logstash可以动态地统一来自不同来源的数据,并将数据规范化到您选择的目的地。清理和民主化您的所有数据,以实现各种高级下游分析和可视化用例。一般Logstash与Elasticsearch和Kiba......
  • 记一次使用spring事件机制失效排查修复
    前言在日常业务开发中过程,我们有时候为了业务解耦,会利用spring的机制,就是利用spring提供的ApplicationListener、ApplicationEventMulticaster等核心API来实现。(注:我这边列的是核心底层API接口,正常我们会用监听事件用@EventListener,发布事件用applicationContext.publishEvent()......
  • Ant Design Vue中的table与pagination的联合使用
    效果: 代码:<a-table:dataSource="dataSource":columns="columns":pagination="pagination"@change="handleTableChange":scroll="{x:'100%',y:600}"></a-table>......
  • 中文自然语言处理小白教程(二)——语料库的安装与使用
    自20世纪80年代以来,随着计算机应用技术的不断发展,世界各大语言都建立了许多不同规模、不同类型的语料库。这些语料库经过深度加工,应用范围也变得越来越广泛,在自然语言处理(NLP)中发挥着越来越重要的作用。因此,语料库已经成为了NLP的重要基础。本章将介绍语料库的基本概念、种类与......
  • ARM架构银河麒麟使用笔记-下载docker软件包及所有依赖包并在离线环境下安装
    ARM架构银河麒麟使用笔记-下载docker软件包及所有依赖包并在离线环境下安装arm银河麒麟aptdocker目的是在arm架构的银河麒麟操作系统V10中安装docker。一、给虚拟机创建快照1.创建qemu-imgsnapshot-cEmptyKylinrootfs.qcow22.查看qemu-imgsnapshot-lrootfs......
  • 【魔改bkui】使用bkui过程中的抓马瞬间
    本文来自腾讯蓝鲸智云社区用户:kai索引0前言1"魔改"支持自定义输入的select前情提要“魔改”第一步——找回组件的灵魂“魔改”第二步——用户体验up?“魔改”第三步——做icon里最靓的仔“魔改”第四步——拗不过的"甲方dad"2TheEnd一些碎碎念前言众所周知,蓝......
  • Quill文档(四):使用Parchment克隆Medium
    为了提供一致的编辑体验,您需要一致的数据和可预测的行为。不幸的是,DOM缺乏这两个特性。现代编辑器的解决方案是维护自己的文档模型来表示它们的内容。对于Quill来说,Parchment就是这样的解决方案。它在自己的代码库中组织,并拥有自己的API层。通过Parchment,您可以定制Quill识别......
  • Supervisor 安装与使用
    一、Supervisor介绍Supervisor是一个用Python编写的进程管理工具,它可以用于监控和控制类UNIX操作系统上的多个进程。它是一个客户端/服务器系统,其中Supervisor的服务器端称为supervisord,负责启动管理的子进程、响应客户端命令、重启崩溃或退出的子进程、记录子进程的st......