• Linux无图形界面环境使用Python+Selenium实践
    简介: 在Linux上使用Selenium和Python来控制浏览器进行自动化测试或者网页数据抓取是常见的需求。本文将介绍如何在Linux无图形界面环境下使用Selenium与Firefox浏览器以headless模式运行,并提供geckodriver、Xvfb和pyvirtualdisplay等工具的安装步骤。Selenium是一个自动化测试工具,它可以模拟用户在浏览器中的操作,例如点击、输入文本、验证元素等。selenium官网介绍:Home:https://selenium.devGitHub:https://github.com/SeleniumHQ/SeleniumPyPI:https://pypi.org/project/selenium/IRC/Slack:Selenium chat room https://www.selenium.dev/support/#ChatRoomselenium支持多种浏览器/驱动程序(Firefox,Chrome,Internet Explorer)以及远程协议。下表是各浏览器对应的驱动。Chromehttps://chromedriver.chromium.org/downloadsEdgehttps://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/Firefoxhttps://github.com/mozilla/geckodriver/releasesSafarihttps://webkit.org/blog/6900/webdriver-support-in-safari-10/本篇以Firefox为例-- 先安装geckodriver:geckodriver是Firefox浏览器的驱动程序,用于与Selenium通信。可以通过以下步骤在Linux上安装geckodriver。访问geckodriver的GitHub页面https://github.com/mozilla/geckodriver/releases,下载适合您系统的压缩包。如果使用其他浏览器对应上表下载对应浏览器驱动。解压下载的文件,并将geckodriver可执行文件所在的目录加入系统的PATH变量。或者直接move到bin目录:mv geckodriver /usr/bin-- 安装firefoxyum install gtk3 wget http://releases.mozilla.org/pub/firefox/releases/116.0.3/linux-x86_64/zh-CN/firefox-116.0.3.tar.bz2 tar jxpvf firefox-116.0.3.tar.bz2 sudo ln -s /root/firefox/firefox /usr/bin/firefox-- 安装selenium在python环境下安装:pip install selenium-- 安装XvfbXvfb是一种虚拟的X窗口服务器,可以模拟图形界面。Ubuntu使用以下命令安装Xvfb: sudo apt-get install Xvfb如果是centos:sudo yum search Xvfb 根据搜索结果找到合适的安装包,通常命名为xorg-x11-server-Xvfb sudo yum install xorg-x11-server-Xvfb.x86_64-- 安装pyvirtualdisplaypyvirtualdisplay是一个Python库,用于在无图形界面环境下触发Xvfb。使用以下命令安装pyvirtualdisplay:pip install EasyProcess pip install xvfbwrapper pip install pyvirtualdisplay-- 编写Python脚本测试现在可以编写一个Python脚本来使用Selenium和Firefox浏览器进行自动化测试或网页数据抓取。以下是一个简单的示例:from selenium import webdriver from selenium.webdriver.firefox.options import Options from pyvirtualdisplay import Display # 创建一个虚拟显示 display = Display(visible=0, size=(1280, 768)) display.start() # 配置Firefox选项 firefox_options = Options() firefox_options.headless = True # 以headless模式运行,具体代码如下: # 创建Firefox browser = webdriver.Firefox(options=firefox_options) # 在这里编写您的代码,例如访问网页、操作元素等 query = 'Selenium的使用' url = f"https://cn.bing.com/search?q={query}" browser.get(url) title = browser.title print("Page title: ", title) browser.save_screenshot('screenshot1.png') # 关闭WebDriver和虚拟显示 browser.quit() display.stop()在这个示例中,我们首先创建一个虚拟显示,然后配置Firefox选项,将其设置为headless模式。然后,创建一个Firefox WebDriver实例,通过它可以直接与浏览器进行交互。在最后,关闭WebDriver和虚拟显示。保存Python脚本尝试运行。可以看到浏览器访问bing搜索页面的title,同时生成了搜索页面的屏幕截图。以headless模式运行selenium,可以不显示浏览器窗口,适合Linux云主机场景,实现自动化测试或者网页数据抓取。这些工具的组合提供了一个可靠且高效的解决方案。
  • 在本地利用虚拟机搭建Hadoop大数据平台
    一、   虚拟机备份:注意:VM虚拟机并不是一个非常稳定的系统,在虚拟化情况下,有时候会出现一些非常莫名奇妙的错误,这就需要我们有足够的克隆备份,以用于错误出现的恢复和追溯,大家可以参考我的虚拟机建设方式。在基础平台中,一般都有一些搭建好的基础组件,例如我们在Hadoop基础平台搭建时候,需要的JDK 1.8 基础组件,我们可以先行搭建好,后在使用的时候,直接克隆,省时省力,在搭建好的基础组件里,我们可以挑选一部分重要的(或者复杂的)进行备份。我们配置到一半的虚拟机,在休息或者阶段性达成时,请在关机时直接进行一次克隆,然后编辑克隆后的虚拟机,按照自己舒服的方式编号即可。在完成配置后,将完成配置的虚拟机移到已完成的组别,然后在完成备份组进行一个备份。虚拟机默认安装系统在C盘,建议有一个大一点的C盘空间,至少100-300G。一、   虚拟机网络设置:虚拟机常用有三种连接网络模式,分别是桥接,NAT,本地,这三种模式都分别代表什么意思?有什么用呢?我用类比法给大家解释一下这个问题。1)  桥接模式:在这种模式下,物理主机好像是一个“交换机”所有的虚拟机都连接这个物理主机的交换机上,所有虚拟机之间的交流不受影响,外界带有DHCP功能的路由器会直接分配给虚拟机地址,需要注意的是,你虚拟机的网段和物理机应在同一个网段,不然无法访问。示意图如下:2)  NAT模式:NAT(网络地址转,用于把内部的私有网络地址转换成可以通讯的公网地)NAT模式相当于在桥接的Vmnet0(虚拟交换机)上又加入了NAT设备和DHCP服务器来自行分配地址,也就是说,相当于在桥接模式的“交换机”上又加了个“路由器”,这样,物理主机和虚拟机的通讯就需要对于这个“路由器”进行配置才能实现和物理主机的通讯。示意图如下:3)  本地模式:本地模式,是NAT模式去掉了NAT设备(只剩DHCP服务器)通过共享网卡可以实现上网。示意图如下:我们在配置Hadoop平台的时候,使用NAT方式。三、   JDK环境配置1)  环境及需要软件:1.  物理机操作系统:windows 10 19032.  VM版本:15.5 pro3.  虚拟机操作系统:CentOS 7 x86_64 18044.  软件需求:Xshell、Xftp、JDK1.8_2112)  虚拟机建立:省略3)  网络设置:1.  网段:192.168.127.02.  网关:192.168.127.13.  V8网卡:192.168.127.884.  主机IP:192.168.127.314)  登录root用户:省略5)  开始配置:1.  IP配置# 修改IP地址# 这步完成后需重新启动$ vim /etc/sysconfig/network-scripts/ifcfg-ens33TYPE="Ethernet" PROXY_METHOD="none" BROWSER_ONLY="no" BOOTPROTO="static" DEFROUTE="yes" IPV4_FAILURE_FATAL="no" IPV6INIT="yes" IPV6_AUTOCONF="yes" IPV6_DEFROUTE="yes" IPV6_FAILURE_FATAL="no" IPV6_ADDR_GEN_MODE="stable-privacy" NAME="ens33" UUID="001ab3ed-d2b2-4697-ba77-a3a235682441" DEVICE="ens33" ONBOOT="yes" IPADDR="192.168.127.31" PREFIX="24" GATEWAY="192.168.127.1"2.  Xshell到主机# 在Xshell上创建Shell连接# 在XFTP中的 /root文件夹下新建一个文件夹为apps,且将JDK1.8传输进去3.  解压缩JDK1.8$ tar -zxvf /root/apps/jdk-8u211-linux-x64.tar.gz# 把解压后的JDK 1.8.0_211通过XFTP拖回apps文件夹4.  设置并且加载JDK1.8# 在环境变量中加入JDK1.8.0_211$ vim /etc/profile#export JAVA_HOME=/root/apps/jdk1.8.0_211 export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export PATH=$JAVA_HOME/bin:$PATH:$HOME/bin重新加载环境变量$ source /etc/profile# 测试$ echo $JAVA_HOME $ java -version5.  关闭主机后,克隆到大数据平台一、   Hadoop平台单节点搭建1)  环境及需要软件:1.  物理机操作系统:windows 10 19032.  VM版本:15.5 pro3.  虚拟机操作系统:CentOS 7 x86_64 18044.  软件需求:Xshell、Xftp、hadoop 2.7.72)  虚拟机建立:省略3)  登录root用户:省略4)  开始配置1.  修改主机名和IP映射2.  IP地址和域名vi /etc/hosts127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.127.31 hadoop313.   关闭防火墙$ systemctl stop firewalld.service $ systemctl disable firewalld.service关闭防火4.  配置SSH免密登录cd ~ ssh-keygen -t rsa #敲三次回车 ssh-copy-id hadoop31 #输入root密码 chmod 700 .ssh5.  正式安装Hadoop# 在文件夹下解压缩tar -zxvf /root/apps/hadoop-2.7.7.tar.gz# 将hadoop安装包移入apps文件夹中:省略,参照JDK# 配置依赖环境cd /root/apps/hadoop-2.7.7/etc/Hadoop vim hadoop-env.sh# 配置文件目录存放位置vim /root/apps/hadoop-2.7.7/etc/hadoop/core-site.xml<configuration> <property> <!--指定hdfs中namenode的地址--> <name>fs.defaultFS</name> <value>hdfs://hadoop31:9000</value> </property> <property> <!--指定hadoop运行时产生文件的存放目录--> <name>hadoop.tmp.dir</name> <value>/root/apps/work/hadoop/tmp</value> </property> </configuration># 配置HDFS副本vim /root/apps/hadoop-2.7.7/etc/hadoop/hdfs-site.xml<configuration> <property> <!--指定hdfs保存数据副本的数量,包括自己,默认为3--> <!--伪分布式模式,此值为1--> <name>dfs.replication</name> <value>1</value> </property> </configuration># 复制mapred组建使mapreduce可编辑cd /root/apps/hadoop-2.7.7/etc/hadoop mv mapred-site.xml.template mapred-site.xml配置Yarn关联MapReduce运行vim /root/apps/hadoop-2.7.7/etc/hadoop/mapred-site.xml<configuration> <property> <!--指定mapreduce运行在yarn上--> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration># 格式化NameNode(第一次启动需要,之后都不需要)cd /root/apps/hadoop-2.7.7 ./bin/hdfs namenode -format启动命令cd /root/apps/hadoop-2.7.7 ./sbin/start-dfs.sh ./sbin/start-yarn.sh测试地址http://hadoop31:50070http://hadoop31:8088
  • [常见FAQ] 第十九届“挑战杯”揭榜挂帅专项赛·华为赛道#常见问题答疑,持续更新!
    Q:这是一场什么样的比赛?“挑战杯”全国大学生课外学术科技作品竞赛是由共青团中央、中国科协、教育部、中国社会科学院和全国学联共同主办的全国性的大学生课外学术实践竞赛。“揭榜挂帅”作为“挑战杯”专项赛之一,企业提需求出题,面向高校广发“英雄帖”,学生团队竞争揭榜。旨在促进产教融合,打造校、企、研成果转化为“桥头堡”。Q:谁可以参加这个比赛?有学生赛道和青年科技人才两个赛道;学生赛道:2024年6月1日以前正式注册的全日制非成人教育的各类高等院校在校专科生、本科生、硕士研究生(不含在职研究生)均可申报作品参赛,以个人或团队形式参赛均可。本校硕博连读生(直博生)若在2024年6月1日以前未通过博士资格考试的,可以按研究生学历申报作品。没有实行资格考试制度的学校,前两年可以按硕士学历申报作品。本硕博连读生,按照四年、两年分别对应本、硕申报,后续则不可申报。青年科技人才赛道:在高等学校、科研院所、企业等各类创新主体中工作的、具有一定科研热情和科研能力的青年科技工作者或者在读博士。参赛人员年龄应在18至35周岁,即1989年6月1日至2006年6月1日期间出生。符合高校学生赛道报名条件的在读博士不得参加青年科技人才赛道比赛,高校青年教师在指导学生参赛的同时不得以参赛人员身份参加同一选题比赛,发榜单位及同发榜单位有相关隶属关系单位的青年不得参加本单位选题比赛。Q:怎么报名参加比赛?登录挑战杯官网(https://fxyh-t.bocmartech.com/jbgs/#/login),在线填写报名信息;点击“挑战杯”官网左侧“作品报名”选项,下载报名信息表打印,并加盖学校公章回传至官网;选手需登录华为云大赛平台(学生:cid:link_0;青年科技人才赛道:https://competition.huaweicloud.com/information/1000042071/introduction)进行实名校验;点击华为云大赛平台菜单栏中的“我的团队”,并点击“组建团队”,所有成员都必须完成实名校验并加入该团队。Q:有问题如何求助?论坛发帖求助:比赛过程中参赛选手可以在论坛中发帖,详细描述您遇到的问题,大赛组委会工作人员将会在工作日工作时间09:00-18:00在社区回复(为保证大赛公平公正原则,大赛官方仅针对报名方式、赛制、赛题、大赛安排等问题进行答疑)。赛事交流群求助:请扫描进入交流群,赛事相关资讯也会第一时间在群内同步,请所有报名选手务必加群。                                      (青年科技人才赛道)                                                             (学生赛道)联系大赛工作人员:如没有得到及时回复,可以添加大赛工作人员微信:15889847842(微信号:HW88886712)。Q:华为云AI开发平台的编程语言用的是华为独创的,还是python、C语言等其他编程语言都能兼容?AI开发,还是主流的Python、C++,没有独创的语言。Q:请问项目检测的样品必须是pcb板吗?可以是其他工业样品吗?是PCB板,数据样例集已给出,请见赛事页面。Q:本次比赛是只会提供这样一个小数据集吗?还是后面会有大数据集呢?本次大赛发放的是样例集,选手可以参考样例集缺陷自行寻找或制作开源数据集制作模型。Q:请问一下后期测试数据里是否也是五类缺陷,会不会有其他类别呢?不会了,缺陷种类是一样的。Q:我们需要检测的就是这块pcb板吗?还是说我们可以基于这个平台检测其他物品,缺陷由我们自己来定。赛题确定为PCB板检测,并且缺陷是样例集里固定的几种。Q:训练的材料也是公司这边提供吗?赛事页面已提供样例集,我们选手可以自行寻找合适的开源数据集。Q:评分用的数据集也是和样例数据集一样吗?一张pcb板只会有一种错误,还是说有几种错误同时在一张板子上的情况?是的,缺陷种类一样,初赛是一张板子一种缺陷。Q:大赛中使用的算法是否必须为本人提出的?使用开源的sota方案是否符合要求?初赛不做限制的,看最终的得分。Q:能够用自己买的910来训练吗?也可以,但不推荐,910很贵。Q:为什么我跑提供的初赛指导里面的yolov5,有调用了HAM,但是NPU AI那个调用一直是0%呀?其实 npu有调用,只是训练消耗的不多,有时候只有小一段时间会使用,所以会看到0这种情况。Q:打榜的分数是累计的吗这个每提交一次就有分,取最高分。Q:收费平台是训练的npu和储存两部分吗,代金券用完要分别在两个平台充钱吗收费是包括npu和存储两部分,但是代金券应该是都包含的,所以不用担心。Q:preprocess的入参date一次只包含一张图吗?是的。Q:请问老师样例集和训练集是同分布的吗,还是只有格式是一样的只能说格式一样。
  • [问题求助] STM32通过ESP8266把jpg文件上传华为云OBS
    我用STM32外接一个摄像头,拍照得到一个jpg图像文件,想通过外接的ESP8266(WiFi方式)把这个jpg文件上传到华为云OBS,请指点一下设计流程,有例程就更好了,谢谢!
  • 存储服务2024.4月技术干货&资讯合集
    技术干货GaussDB数据量与分区策略分析https://bbs.huaweicloud.com/forum/thread-02106149308401380040-1-1.htmlGaussDB分页查询的实现方法https://bbs.huaweicloud.com/forum/thread-02106149308219906039-1-1.html高可用prometheus集群方案选型分享https://bbs.huaweicloud.com/forum/thread-02120149171280544026-1-1.html数据结构小实践https://bbs.huaweicloud.com/forum/thread-0205148913374176023-1-1.html常用的Python 正则表达式笔记分享https://bbs.huaweicloud.com/forum/thread-0229148809003688021-1-1.htmlOBS常用存储类别及介绍笔记分享https://bbs.huaweicloud.com/forum/thread-02107148640450505013-1-1.htmlOBS存储加密方式https://bbs.huaweicloud.com/forum/thread-02107148640269972012-1-1.html计算机常用基础常识https://bbs.huaweicloud.com/forum/thread-02107148640095926011-1-1.htmlC线性链表https://bbs.huaweicloud.com/forum/thread-02107148566274864009-1-1.htmlLinux基础与服务器架构综合小实践https://bbs.huaweicloud.com/forum/thread-0208148385106201002-1-1.html数码管的动态显示https://bbs.huaweicloud.com/forum/thread-0229148385031520001-1-1.htmlLinux磁盘配额小实践https://bbs.huaweicloud.com/forum/thread-0208148316143191001-1-1.htmlNUMA架构笔记分享https://bbs.huaweicloud.com/forum/thread-0291148012681064004-1-1.htmlNUMA-Aware亲和性优化https://bbs.huaweicloud.com/forum/thread-0231148012477529001-1-1.htmlGaussDB分布式与单机模式的比较https://bbs.huaweicloud.com/forum/thread-0252147925786150001-1-1.html中断源类型详解https://bbs.huaweicloud.com/forum/thread-02109147598839758040-1-1.html资讯【话题交流】说说大家都知道的认证考试和学习推荐讨论https://bbs.huaweicloud.com/forum/thread-0208149308741557029-1-1.html
  • 【话题交流】说说大家都知道的认证考试和学习推荐讨论
    随着IT技术的不断发展,知识的不断更新迭代,大家讨论讨论说说大家都知道的认证考试和学习推荐,欢迎大家一起来讨论所有IT方面都可以、大数据、物联网、人工智能、云计算、区块链、项目管理等等等……都可以来说说有没有推荐的
  • GaussDB数据量与分区策略分析
    简要概述我们可以得出一些关于GaussDB数据库是否需要分区,以及如何进行分区的初步建议。分区是一种数据库管理技术,用于提高数据处理效率、优化存储使用和提高系统的可维护性。通常,分区决策是基于数据量和表的大小来决定的。详细分析1. 分区策略的选择分区策略的选择取决于数据的特性和表的使用情况。例如,具有明显区间性特征的字段(如日期、区域、数值等)适合进行表分区。时间字段是最常见的分区字段,因为业务查询经常具有明显的区间范围特征。此外,对于数据量大的表,分区可以有效提升数据扫描效率,降低IO开销。2. 分区的标准和方法GaussDB支持多种分区方法,如RANGE分区、INTERVAL分区、LIST分区和HASH分区。RANGE分区是基于连续范围进行的分区,适用于数据范围固定的字段。INTERVAL分区是基于固定间隔进行的分区,适用于时间字段。LIST分区是基于特定列表值进行的分区,适用于枚举类型字段。HASH分区是基于哈希函数进行的分区,适用于任意类型的字段。3. 分区的限制和注意事项一些分区时的限制,例如二级分区表的叶子节点个数不能超过1048575个,一级分区无限制。同时,还应注意分区策略可能会受到磁盘容量不足的影响,需要合理规划磁盘分区以避免容量不足。总结建议综上所述,GaussDB的数据量达到一定程度并且表的大小符合分区的要求时,建议进行分区。具体的分区策略应基于数据特性和业务需求来确定,考虑范围性字段、时间字段等适合进行分区的字段。在实施分区之前,需要评估磁盘容量,确保分区不会因容量不足而影响性能。GaussDB的数据量是否需要分区取决于多个因素,包括但不限于数据的规模、查询性能需求以及存储资源等。一般来说,当表的数据量较大,查询频繁并且需要优化查询性能时,可以考虑进行分区。GaussDB支持多种分区方式,包括Range分区、Interval分区、List分区和Hash分区1。具体的分区策略需要根据实际的数据特征和业务需求来制定。例如,如果你的数据具有明显的时间范围特征,你可以选择Range或者Interval分区;如果你希望根据特定的值来进行分区,可以选择List分区;如果你希望根据数据的散列值来进行分区,可以选择Hash分区。此外,GaussDB还支持二级分区,即在一级分区的基础上进一步划分二级分区。但是需要注意的是,二级分区表的二级分区(叶子节点)个数不能超过1048575个,一级分区无限制,但一级分区下面至少有一个二级分区。总的来说,GaussDB的分区策略是为了提高查询性能和优化存储资源的使用,具体是否需要分区以及如何分区,需要根据你的实际需求和数据特征来决定。
  • GaussDB分页查询的实现方法
    概述GaussDB的分页查询通常涉及到数据库的排序和数据量的限制。在数据库管理系统中,分页查询可以帮助用户一次获取少量数据,减少数据传输量和内存使用,提高查询效率。接下来将从多个角度详细探讨GaussDB分页查询的具体实现方法和优化技巧。分页查询的SQL写法在GaussDB中,分页查询可以通过以下两种SQL语句来实现:第一种:子查询法SELECT * FROM ( SELECT a.*, ROWNUM rn FROM (SELECT * FROM tab1 WHERE status = 1 ORDER BY id) a ) b WHERE rn <= 500这里使用了一个子查询来生成行号,并通过ROWNUM限制行数不超过500。第二种:LIMIT用法SELECT * FROM tab1 WHERE status = 1 ORDER BY id LIMIT 500, 1这种写法使用了LIMIT语句来跳过前面的数据行,直接选取接下来的500行数据。场景优化及建议当查询的数据量非常大时,建议使用索引来优化查询性能。如果大部分查询都是访问前几页数据,建议使用排序字段的索引来提高效率。对于需要频繁翻页的场景,建议使用不排序的分页查询方式,如使用LIMIT语句。当需要对统计分页数据总数时,建议缓存结果或合理设计查询逻辑以避免重复计算。分页查询的性能优化索引策略:适当地创建和使用索引可以大幅提高查询速度,特别是对于排序和筛选操作。SQL语句优化:合理编写SQL语句,避免使用过多的子查询,减少数据处理的层级。数据库引擎优化:选择合适的数据库引擎,例如GaussDB的并行执行能力可以有效地处理大数据量的分页查询。在GaussDB中实现分页查询,您可以使用LIMIT和OFFSET关键字。LIMIT关键字用来限制返回的记录数量,而OFFSET关键字用来跳过前面的记录。这两个关键字通常一起使用,以实现分页的效果。以下是使用LIMIT和OFFSET关键字的一个基本例子:SELECT * FROM your_table_nameLIMIT 10OFFSET 20;在这个例子中,LIMIT 10指定了每页显示10条记录,而OFFSET 20指定了从第20条记录开始显示。这意味着查询结果将显示第21到第30条记录。请注意,不同的数据库系统可能有不同的分页查询语法。在GaussDB中,上述方法是实现分页查询的标准方式。在实际使用中,您可能需要根据具体的查询需求和数据表结构调整LIMIT和OFFSET的值。深入研究如何在保持高性能的同时,对大规模数据集进行有效的分页查询?在对大规模数据集进行分页查询时,为了保持高性能,可以采取以下几种策略:使用覆盖索引覆盖索引是指查询时只需要访问索引而无需访问表中的数据行。通过对表中的字段建立索引,并在查询时使用这些索引,可以显著提高查询速度。例如,如果有一个字段id是自增的,并且是连续增长的,可以在id上建立索引,然后在查询时使用LIMIT和OFFSET来快速定位到需要的页面。延迟关联延迟关联是一种优化策略,它涉及到先通过索引获取到需要的主键,然后再根据主键关联原表以获取完整数据,而不是通过二级索引获取主键后再遍历数据页。这样可以避免大量的随机I/O请求,从而提高查询效率。使用游标分页游标分页是通过记录的唯一标识符来定位分页的起点和终点,避免了大量的跳跃查询。这种方法通常适用于有唯一标识符的字段,如id或row_number等。选择合适的分页策略在某些情况下,可能需要根据实际应用场景选择最合适的数据分页策略。例如,如果数据是连续增长的,可以选择基于ID的分页;如果数据是无序的,可能需要使用其他方法,如基于时间的分页或其他业务逻辑上的分页。利用缓存如果数据不是实时变化的,可以考虑使用缓存来存储最近的分页结果,减少对数据库的查询次数,从而提高性能。分区表分页如果数据表非常大,可以考虑将其分区,每个分区包含一部分数据。这样,在进行分页查询时,只需访问包含所需数据的分区,减少了不必要的数据扫描。硬件和资源优化除了查询优化外,还可以通过增加服务器资源、使用更快的存储解决方案(如SSD)、优化数据库配置等方式来提高整体性能。综上所述,通过对大规模数据集采用适当的分页策略和技术,可以在保持高性能的同时有效地进行分页查询。在设计分页查询功能时,如何解决数据库资源消耗与用户体验之间的平衡?在设计分页查询功能时,解决数据库资源消耗与用户体验之间的平衡是一个重要的考虑因素。以下是一些关键点,可以帮助您在开发过程中找到这种平衡:1. 优化查询语句确保您的查询尽可能高效,避免使用复杂的子查询和不必要的联接操作。使用正确的索引可以大大减少查询所需的IO操作,从而降低资源消耗。2. 使用合理的分页大小默认的分页大小应该适应大多数用户的浏览习惯,同时考虑到后端服务的处理能力。过大或过小的分页尺寸都可能导致资源过度消耗或不满足用户需求。3. 提供自定义分页选项允许用户根据自己的偏好设置分页大小,可以在保证用户体验的同时,减轻服务器的压力。4. 引入缓存机制对于不经常变化的数据,可以通过缓存来减少数据库访问次数,从而节省资源。合理设计的缓存策略可以有效缓解热点数据的查询压力。5. 监控和调优实施监控工具来跟踪分页查询的性能指标,如响应时间、吞吐量等。根据监控数据进行调优,以确保资源消耗保持在可接受的范围内。6. 负载均衡如果可能的话,使用负载均衡器来分散流量,减轻单个服务器的负担。这有助于在高负载下维持稳定性和可用性。7. 异步处理对于非关键路径上的分页查询,可以考虑使用异步处理的方式,让用户界面保持响应,同时在后台慢慢处理数据。8. 用户反馈收集用户反馈,了解用户在使用分页功能时的真实感受,并根据这些反馈来调整设计和参数。通过综合考虑以上因素,可以在确保数据库资源得到合理利用的同时,为用户提供一个流畅且友好的分页查询体验。考虑到分页查询在大数据环境下的局限性,未来数据库技术发展趋势中可能出现哪些替代方案?在大数据环境下,分页查询确实存在一定的局限性,因为它可能会导致大量数据的重复加载,特别是在高交互的应用场景中。未来的数据库技术发展趋势可能会出现以下几个替代方案来解决这一问题:1. 动态数据流处理未来的数据库技术可能会更加注重实时数据处理能力的提升,通过动态数据流处理技术,可以不断地向用户展示最新的数据片段,而不是一次性加载整个数据集。2. 智能预加载算法通过机器学习和人工智能技术,数据库可以预测用户的查询模式,并提前加载可能被请求的数据,以此来减少等待时间和资源消耗。3. 分布式计算和存储随着云计算和边缘计算的发展,数据库技术可能会越来越多地依赖于分布式计算和存储解决方案,以提高处理大数据的能力和效率。4. 内存数据库和缓存为了减少磁盘I/O操作,未来的数据库技术可能会更多地使用内存数据库和缓存技术,以提高数据访问的速度。5. 微服务和容器化通过微服务和容器化的架构,可以将数据库分解成多个小块,每个小块负责处理特定类型的查询,从而提高整体的灵活性和效率。6. 无SQL数据库无SQL数据库(NoSQL databases)提供了不同于传统关系型数据库的模型,它们通常更适合于处理大规模的非结构化数据,可能在未来的大数据环境中扮演更重要的角色。7. 数据虚拟化数据虚拟化技术可以创建一个抽象层,使得用户可以直接访问不同来源和格式的数据,而不需要关心数据实际存储在哪里,这可能有助于简化大数据环境下的数据管理。8. 增强现实和虚拟现实虽然目前还不是主流技术,但增强现实(AR)和虚拟现实(VR)技术在未来可能会提供一种全新的数据可视化和交互方式,尤其是在需要复杂数据可视化的领域。这些潜在的替代方案表明,未来的数据库技术发展将会集中在提高处理速度、降低资源消耗以及提供更加智能化和个性化的用户体验。随着技术的不断进步,这些新兴的解决方案有望克服现有的大数据挑战。总结分页查询是数据库常用的操作,尤其是在数据量较大时。合理使用SQL语句、索引以及数据库引擎的特性,可以有效地提高分页查询的性能。在实际应用中,应根据具体情况选择合适的分页查询方式和优化策略。审核中
  • [技术干货] 高可用prometheus集群方案选型分享
      Prometheus采用Pul模型收集监控数据,服务高可用意味着同一个服务需要至少两个节点同时拉取或者切换为Push模型,使用一致性哈希,将不同实例的Metrics推送到固定推送到其中一台服务,这个模式优势是,在保障服务可用性的同时,资源消耗量少一半;新节点不需要重新配置抓取规则可以做到快速平行扩容。但缺点是,节点故障将导致历史数据丢失。应用于生产环境的监控服务,单机Promtheus往往是无法满足需求的,此时就要搭建一套Prometheus集群,此时就需要考虑:服务高可用:服务要冗余备份,以消除单点故障。水平可扩展:可以通过增加服务数量,线性提高服务能力。数据持久化:节点故障数据不丢失、海量历史数据存储数据一致性:冗余结点之间数据需要保证一致性。选型⼀      Prometheus 根据功能或服务维度进行拆分,即如果要采集的服务比较多,一个Prometheus 实例就配置成仅采集和存储某一个或某一部分服务的指标,这样根据要采集的服务将 Prometheus 拆分成多个实例分别去采集,也能一定程度上达到水平扩容的目的。优点:服务被拆分给多个prometheus实例例收集,从而降低了单实例的性能瓶颈不同的prometheus实例配置可以不同拆分存储,分摊采集指标的量缺点统⼀查询入⼝不统⼀,每个prometheus都是一个查询入口采集数据依然存在本地,受本地磁盘容量和io限制选型⼆      针对选型一,一个Prometheus实例可能连这单个服务的采集任务都扛不住。     prometheus需要向这个服务所有后端实例发请求采集数据,由于后端实例数量规模太大,采集并发量就会很高,一方面对节点的带宽、CPU、磁盘lo都有一定的压力,另一方面Prometheus使用的磁盘空间有限,采集的数据量过大很容易就将磁盘塞满了,通常要做一些取舍才能将数据量控制在一定范围,但这种取舍也会降低数据完整和精确程度,不推荐这样做。那么我们可以给这种大规模类型的服务做一下分片(Sharding),将其拆分成多个group,让一个Prometheus 实例仅采集这个服务背后的某一个group 的数据,这样就可以将这个大体量服务的监控数据拆分到多个Prometheus 实例上。优点︰解决单个服务监控指标大,利用切片方式让不同prometheus负责不同分片可以做Prometheus水平扩容缺点︰加剧了监控数据落盘的分散程度,使用grafana查询数据依然需要添加多个数据源不同数据源之间的数据还不能聚合查询选型三      可以让Prometheus 不负责存储,仅采集数据并通过remote write接口方式写入远程存储的adapter,远程存储使用OpenTSDB或InfluxDB这些支持集群部署的时序数据库。然后Grafana添加我们使用的时序数据库作为数据源来查询监控数据来展示。优点数据存储远程写入,实现单数据源的查询缺点:查询语句得使用远程数据源的语法,并不能使用prometheus的promeQL语法查询选型四       虽然上面我们通过一些列操作将Prometheus进行了分布式改造,但并没有解决Prometheus 本身的高可用问题,即如果其中一个实例挂了,数据的查询和完整性都将受到影响,那么我们可以将所有Prometheus实例都使用两个相同副本,分别挂载数据盘,它们都采集相同的服务,所以它们的数据是一致的,查询它们之中任意一个都可以,所以可以在它们前面再挂一层负载均衡,所有查询都经过这个负载均衡分流到其中一台Prometheus,如果其中一台挂掉就从负载列表里踢掉不再转发。优点:保障了prometheus的高可用缺点:数据并不能保证完全一致,当其中一台故障恢复后,他将丢失该时间的数据选型五        thanos架构,可以帮我们简化分布式 Prometheus的部署与管理,并提供了一些的高级特性︰全局视图,长期存储,高可用,该架构使用grpc保持各个组件的通讯,sidecar组件负责连接Prometheus,将其数据提供给Thanos Query查询,并且/或者将其上传到对象存储,以供长期存储。Query组件实现了Prometheus APl,将来自下游组件提供的数据进行聚合最终返回给查询数据的client(如grafana),类似数据库中间件。Thanos Store Gateway组件将对象存储的数据暴露给Thanos Query去查询,Thanos Compact组件将对象存储中的数据进行压缩和降低采样率,大时间区间监控数据查询的速度。Thanos Ruler组件对监控数据进行评估和告警,还可以计算出新的监控数据,将这些新数据提供给Thanos Query查询并且/或者上传到对象存储,以供长期存储。优点:采集数据可永久性保存全局Query入口查询支持PromeQL语法。支持监控数据的聚合和去重保障prometheus的高可用缺点︰sidecar如果分布在不同地域,容易造成较高延迟,查询速度会较慢。但可以用Receiver模式(还不稳定)
  • 数据结构小实践
    单向链表的概念单向链表是一种线性数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。在单向链表中,数据元素之间是单向连接的,每个节点只有一个指针指向下一个节点,而没有指向前一个节点的指针。因此,一旦形成链表,就不能从任意节点直接访问前一个节点,只能从头节点开始沿着指针依次访问每个节点单向链表的基本操作单向链表的主要操作包括插入、删除和遍历等。插入操作:在链表的任意位置插入一个新节点。这通常涉及到创建一个新的节点,然后将其插入到链表的特定位置,并更新相应节点的指针2。删除操作:删除链表中指定位置的节点。这通常需要找到要删除的节点,然后将前一个节点的指针跳过该节点,指向下一个节点,最后释放该节点的资源2。遍历操作:遍历链表,访问链表中的每个节点。这可以通过从头节点开始,逐步移动到尾节点来实现下列给定程序是建立一个带头结点的单向链表,并用随机函数为各结点赋值。函数fun的功能是将单向链表结点(不包括头结点)数据域为偶数的值累加起来,并且作为函数值返回。#include <stdio.h>#include <conio.h>#include <stdlib.h>typedef struct aa{ int data;  struct aa *next;} NODE;int fun (NODE *h){ int sum=0;  NODE *p;  p=h->next;/*************found**************/  while(p->next)       { if(p->data%2==0)             sum+=p->data;/*************found**************/          p=h->next;       }  return sum;}NODE *creatlink(int n){   NODE *h,*p,*s;  int i;  h=p=(NODE*)malloc(sizeof(NODE));  for(i=1;i<n;i++)  {         s=(NODE*)malloc(sizeof(NODE));               s->data=rand()%16;               s->next=p->next;               p->next=s;               p=p->next;  }  p->next=NULL;  return h;}outlink(NODE *h){ NODE  *p;  p=h->next;  printf("\n\n The LIST :\n\n HEAD");  while(p)    { printf("->%d",p->data);      p=p->next;}  printf("\n");}void main(){ NODE *head; int sum;  system("CLS");  head=creatlink(10);  outlink(head);  sum=fun(head);  printf("\nSUM=%d",sum);}【解题思路】本题考查的是在这种链表的数据结构中,必须利用指针变量才能实现,即一个节点中应包含一个指针变量,用以存放下一节点的地址。建立单项链表的一般步骤是:建立头指针→建立第一个节点→头指针指向第一个节点→建立第二个节点→第一个节点的指针与指向第二个节点→…→最后一个节点的指针指向null。本题重点是:了解链表的基本思想和相关算法,理解有关链表插入及删除时,指针移动的先后顺序问题,注意指针的保存和归位。while循环条件是判断链表是否结束,所以改为while (p!=NULL),要指向下个节点所以改为p=p->next。注意事项在使用单向链表时,需要注意的是,由于链表的节点之间是通过指针相连的,因此在插入和删除节点时,需要特别小心处理这些指针关系,以确保链表的正确性和完整性。同时,由于单向链表不支持快速反向访问,所以在需要频繁访问链表尾部或中间节点的场景下,可能不如双向链表或数组方便
  • 常用的Python 正则表达式笔记分享
     正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。 Python 自1.5版本起增加了 re 模块,是用于处理字符串的强大工具,re 模块使 Python 语言拥有全部的正则表达式功能。compile() 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。本章节主要介绍Python中常用的正则表达式处理函数。re.match函数re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。函数语法:re.match(pattern, string, flags=0)函数参数说明:参数描述pattern匹配的正则表达式string要匹配的字符串。flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。正则表达式修饰符 - 可选标志正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:修饰符描述re.I使匹配对大小写不敏感re.L做本地化识别(locale-aware)匹配re.M多行匹配,影响 ^ 和 $re.S使 .匹配包括换行在内的所有字符re.U根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.re.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。匹配成功re.match方法返回一个匹配的对象,否则返回None。我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。匹配对象方法描述group(num=0)匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。groups()返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。实例import re print(re.match('www', 'www.python.org').span())  # 在起始位置匹配 print(re.match('org', 'www.python.org'))         # 不在起始位置匹配以上实例运行输出结果为:(0, 3) None实例import re line = "Cats are smarter than dogs" matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I) if matchObj:   print ("matchObj.group() : ", matchObj.group())   print ("matchObj.group(1) : ", matchObj.group(1))   print ("matchObj.group(2) : ", matchObj.group(2)) else:   print ("No match!!")以上实例执行结果如下:matchObj.group() : Cats are smarter than dogs matchObj.group(1) : Cats matchObj.group(2) : smarterre.search 方法re.search 扫描整个字符串并返回第一个成功的匹配。函数语法:re.search(pattern, string, flags=0)函数参数说明:参数描述pattern匹配的正则表达式string要匹配的字符串flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等匹配成功re.search方法返回一个匹配的对象,否则返回None。 我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。匹配对象方法描述group(num=0)匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。groups()返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。实例import re print(re.search('www', 'www.python.org').span())  # 在起始位置匹配 print(re.search('org', 'www.python.org').span())  # 不在起始位置匹配以上实例运行输出结果为:(0, 3) (11, 14)实例import re line = "Cats are smarter than dogs"; searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I) if searchObj:   print ("searchObj.group() : ", searchObj.group())   print ("searchObj.group(1) : ", searchObj.group(1))   print ("searchObj.group(2) : ", searchObj.group(2)) else:   print ("Nothing found!!")以上实例执行结果如下:searchObj.group() : Cats are smarter than dogs searchObj.group(1) : Cats searchObj.group(2) : smarterre.match 与 re.search 的区别re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。实例import re line = "Cats are smarter than dogs"; matchObj = re.match( r'dogs', line, re.M|re.I) if matchObj:   print ("match --> matchObj.group() : ", matchObj.group()) else:   print ("No match!!") matchObj = re.search( r'dogs', line, re.M|re.I) if matchObj:   print ("search --> matchObj.group() : ", matchObj.group()) else:   print ("No match!!")以上实例运行结果如下:No match!! search --> matchObj.group() : dogs检索和替换Python 的 re 模块提供了 re.sub 用于替换字符串中的匹配项。语法:re.sub(pattern, repl, string, count=0)参数:pattern : 正则中的模式字符串。repl : 替换的字符串,也可为一个函数。string : 要被查找替换的原始字符串。count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。实例import re phone = "2004-959-559 # 这是一个电话号码" # 删除注释 num = re.sub(r' #.*$', "", phone) print ("电话号码 : ", num) # 移除非数字的内容 num = re.sub(r'\D', "", phone) print ("电话号码 : ", num)以上实例执行结果如下:电话号码 : 2004-959-559 电话号码 : 2004959559re.compile 函数compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。语法格式为:re.compile(pattern[, flags])参数:pattern : 一个字符串形式的正则表达式flags 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:re.I 忽略大小写re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境re.M 多行模式re.S 即为' . '并且包括换行符在内的任意字符(' . '不包括换行符)re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库re.X 为了增加可读性,忽略空格和' # '后面的注释实例>>> import re >>> pattern = re.compile(r'\d+')                    # 用于匹配至少一个数字 >>> m = pattern.match('one12twothree34four')        # 查找头部,没有匹配 >>> print m None >>> m = pattern.match('one12twothree34four', 2, 10) # 从'e'的位置开始匹配,没有匹配 >>> print m None >>> m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,正好匹配 >>> print m                                         # 返回一个 Match 对象 <_sre.SRE_Match object at 0x10a42aac0> >>> m.group(0)   # 可省略 0 '12' >>> m.start(0)   # 可省略 0 3 >>> m.end(0)     # 可省略 0 5 >>> m.span(0)    # 可省略 0 (3, 5)在上面,当匹配成功时返回一个 Match 对象,其中:group([group1, …]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group()或 group(0);start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;span([group]) 方法返回 (start(group), end(group))。实例>>> import re >>> pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I)   # re.I 表示忽略大小写 >>> m = pattern.match('Hello World Wide Web') >>> print(m)                               # 匹配成功,返回一个 Match 对象 <_sre.SRE_Match object at 0x10bea83e8> >>> m.group(0)                            # 返回匹配成功的整个子串 'Hello World' >>> m.span(0)                             # 返回匹配成功的整个子串的索引 (0, 11) >>> m.group(1)                            # 返回第一个分组匹配成功的子串 'Hello' >>> m.span(1)                             # 返回第一个分组匹配成功的子串的索引 (0, 5) >>> m.group(2)                            # 返回第二个分组匹配成功的子串 'World' >>> m.span(2)                             # 返回第二个分组匹配成功的子串 (6, 11) >>> m.groups()                            # 等价于 (m.group(1), m.group(2), ...) ('Hello', 'World') >>> m.group(3)                            # 不存在第三个分组 Traceback (most recent call last):  File "<stdin>", line 1, in <module> IndexError: no such groupfindall在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。注意: match 和 search 是匹配一次 findall 匹配所有。语法格式为:re.findall(pattern, string, flags=0)参数:参数描述pattern匹配的正则表达式string要匹配的字符串。flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。查找字符串中的所有数字:实例import re result1 = re.findall(r'\d+', 'TechLab 123 google 456') result2 = re.findall(r'\d+', 'Tech88Lab123google456') print(result1) print(result2)输出结果:['123', '456'] ['88', '123', '456']re.finditer和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。re.finditer(pattern, string, flags=0)参数:参数描述pattern匹配的正则表达式string要匹配的字符串。flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。实例import re it = re.finditer(r"\d+","12a32bc43jf3") for match in it:    print (match.group())输出结果:12 32 43 3re.splitsplit 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:re.split(pattern, string[, maxsplit=0, flags=0])参数:参数描述pattern匹配的正则表达式string要匹配的字符串。maxsplit分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。实例>>> import re >>> re.split('\W+', 'python, python, python.') ['python', 'python', 'python', ''] >>> re.split('(\W+)', ' python, python, python.') ['', ' ', 'python', ', ', 'python', ', ', 'python', '.', ''] >>> re.split('\W+', ' python, python, python.', 1) ['', 'python, python, python.'] >>> re.split('a*', 'hello world')   # 对于一个找不到匹配的字符串而言,split 不会对其作出分割 ['hello world']附录正则表达式对象re.RegexObjectre.compile() 返回 RegexObject 对象。re.MatchObjectgroup() 返回被 RE 匹配的字符串。start() 返回匹配开始的位置end() 返回匹配结束的位置span() 返回一个元组包含匹配 (开始,结束) 的位置正则表达式模式模式字符串使用特殊的语法来表示一个正则表达式:字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。多数字母和数字前加一个反斜杠时会拥有不同的含义。标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。反斜杠本身需要使用反斜杠转义。由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如r'\t',等价于\\t )匹配相应的特殊字符。下表列出了正则表达式模式语法中的特殊元素。如果你使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。模式描述^匹配字符串的开头$匹配字符串的末尾。.匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。[...]用来表示一组字符,单独列出:[amk]匹配'a','m'或'k'[^...]不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。re*匹配0个或多个的表达式。re+匹配1个或多个的表达式。re?匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式re{ n}匹配n个前面表达式。例如,"o{2}"不能匹配"Bob"中的"o",但是能匹配"food"中的两个o。re{ n,}精确匹配n个前面表达式。例如,"o{2,}"不能匹配"Bob"中的"o",但能匹配"foooood"中的所有o。"o{1,}"等价于"o+"。"o{0,}"则等价于"o*"。re{ n, m}匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式a|b匹配a或b(re)匹配括号内的表达式,也表示一个组(?imx)正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。(?-imx)正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。(?: re)类似(...), 但是不表示一个组(?imx: re)在括号中使用i, m, 或 x 可选标志(?-imx: re)在括号中不使用i, m, 或 x 可选标志(?#...)注释.(?= re)前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。(?! 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个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。正则表达式使用实例字符匹配实例描述python匹配 "python".字符类实例描述[Pp]ython匹配"Python" 或"python"rub[ye]匹配 "ruby" 或 "rube"[aeiou]匹配中括号内的任意一个字母[0-9]匹配任何数字。类似于[0123456789][a-z]匹配任何小写字母[A-Z]匹配任何大写字母[a-zA-Z0-9]匹配任何字母及数字[^aeiou]除了aeiou字母以外的所有字符[^0-9]匹配除了数字外的字符特殊字符类实例描述.匹配除 \n之外的任何单个字符。要匹配包括\n在内的任何字符,请使用像[.\n]的模式。\d匹配一个数字字符。等价于[0-9]。\D匹配一个非数字字符。等价于[^0-9]。\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于[\f\n\r\t\v]。\S匹配任何非空白字符。等价于[^ \f\n\r\t\v]。\w匹配包括下划线的任何单词字符。等价于[A-Za-z0-9_]。\W匹配任何非单词字符。等价于[^A-Za-z0-9_]。
  • OBS常用存储类别及介绍笔记分享
    对象存储服务(Object Storage Service,OBS)是一个基于对象的海量存储服务,它的基本组成是桶和对象,桶是OBS中存储对象的容器,对象是OBS中数据存储的基本单位,它能够为客户提供海量、安全、高可靠、低成本的数据存储能力。华为云在全球多区域部署了OBS基础设施,用户可以根据自身需要指定区域使用OBS,由此获得更快的访问速度和实惠的服务价格。OBS系统是一项面向Internet访问的服务,用户可以随时随地连接到Internet的电脑上,因为OBS提供了基于HTTP/HTTPS协议的Web服务接口,用户可以通过OBS管理控制台或各种OBS工具访问和管理存储在OBS中的数据。企业也可以在自己的应用程序中随心管理自己存储在OBS上的数据,因为OBS对外提供了支持SDK和OBS API接口,企业的开发人员可以根据OBS提供的SDK和API接口随心的调用存储在OBS上的数据。OBS提供了四种存储类别:标准存储、低频访问存储、归档存储、深度归档存储(受限公测中),从而在各个方面满足客户业务对存储性能、成本的不同诉求。标准存储:它的访问延时低、吞吐量高,所以它适用于有大量热点文件(平均一个月多次)或小文件(小于1MB),并且适用于需要频繁访问数据的业务场景,比如:大数据、移动应用、热点视频、社交图片等场景。低频访问存储:它有和标准存储一样的数据持久性、吞吐量以及访问时延,且成本较低,就是可用性略低于标准存储,它适用于不频繁访问(平均一年少于12次)但在需要时也要求快速访问数据的业务场景,比如:文件同步/共享、企业备份等场景。归档存储:它的特点是安全、持久且成本极低,可以用来替代磁带库。归档存储为了保持成本低廉,数据取回时间可能长达数分钟到数小时不等,所以它适用于很少访问(平均一年访问一次)数据的业务场景,比如:数据归档、长期备份等场景。深度归档存储:它的成本比归档存储更低,它适用于长期不访问(平均几年访问一次)数据的业务场景。OBS共用5大优势,数据稳定,业务可靠:OBS支撑华为手机云相册,能够支持数亿用户的访问,能够给应用提供稳定可靠的数据;多重防护,授权管理:OBS通过可信云认证,让数据安全放心;千亿对象,千万并发:OBS通过智能调度和响应,优化数据访问路径、传输加速等技术,可以为各场景下用户的千亿对象提供千万级并发、超高带宽、稳定低时延的数据访问体验;简单易用,便于管理:OBS提供SDK和标准REST API接口,能够让业务快速上云,OBS还有管理控制台或各种OBS工具,可以使用户方便管理自己存储在OBS上的数据;数据分层,按需使用:OBS提供按量计费和包年包月两种支付方式,用户可以随心选择的适合自己的支付方式。OBS有很多的适用场景,比如:大数据分析、静态网站托管、在线视频点播、基因测序、智能视频监控、备份归档等,这么多的使用场景总有一种满足你。2022年“华为云双12”已重磅开启,华为云以优质的产品解决方案及服务全方位满足企业上云、用云需求,助力企业实现创新增效。
  • OBS存储加密方式
    OBS对象存储是华为云提供的一种高效、安全、可靠的云存储服务,它提供了数据加密和备份机制,为用户的数据安全性提供了更可靠的保障。数据加密在OBS对象存储中,对数据的加密是采用AES-256位加密算法,这是一种经典、高安全性的算法。用户可以选择在上传文件时对文件进行加密处理,或者在创建桶时对整个桶进行加密处理。同时,OBS对象存储还提供了多种密钥管理模式,用户可以自主选择对密钥的管理方式。这些功能可以帮助用户更好地保护自己的数据,确保数据不被未经授权的人员访问。备份机制备份是保障数据安全的重要手段之一,OBS对象存储提供了多层次的备份机制,包括跨机房备份和跨地域备份。跨机房备份可以保障在主机房出现故障时,数据能够快速备份到备用机房,确保数据的可用性。跨地域备份则能够保障在某个地域发生不可抗力因素时,数据能够备份到其他地域,避免数据的丢失。同时,OBS对象存储还提供了数据版本控制功能,用户可以对数据进行历史版本的管理和查询,确保数据的完整性和可靠性。总结作为一种高效、安全、可靠的云存储服务,OBS对象存储为用户提供了强大的数据加密和备份机制,为用户的数据安全性提供了更可靠的保障。除此之外,OBS对象存储还具备高可靠性和高性能的特点,可以满足用户对于数据存储和处理的需求。因此,对于企业和组织来说,选择OBS对象存储作为数据存储的方案是一个明智的选择。
  • 计算机常用基础常识
    计算机的发展、类型及其应用领域。计算机(computer)是一种能自动、高速进行大量算术运算和逻辑运算的电子设备。 其特点为:速度快、精度高、存储容量大、通用性强、具有逻辑判断和自动控制能力。第一台计算机:ENIAC,美国,1946年 宾夕法尼亚大学  冯诺依曼 “存储程序”和“程序控制”冯诺依曼思想的核心要点是:    1)计算机的基本结构应由五大部件组成:运算器、控制器、存储器、输入设备和输出设备。    2)计算机中应采用二进制形式表示数据和指令。    3)采用“存储程序”和“程序控制”的工作方式。 计算机的发展过程阶段年份物理器件软件特征应用范围第一代1946-1959电子管机器语言、汇编语言科学计算第二代1959-1964晶体管高级语言科学计算、数据处理、工业控制第三代1964-1970小规模集成电路操作系统科学计算、数据处理、工业控制、文字处理、图形处理第四代1970-至今大规模集成电路数据库网络等各个领域主要特点:运算速度快、精确度高、具有记忆和逻辑判断能力计算机的主要应用科学计算:例如:气象预报、海湾战争中伊拉克导弹的监测数据/信息处理:例如:高考招生中考生录取与统计工作,铁路、飞机客票的预定系统,银行系统的业务管理计算机控制计算机辅助系统:例如:用CAI演示化学反应人工智能:例如:代替人类到危险的环境中去工作办公自动化系统中的应用:例如:Internet发emailCBE:计算机辅助教育CAI:计算机辅助教学CMI:计算机管理教学CAD:计算机辅助设计CAT:计算机辅助翻译CAM:计算机辅助制造CAE:计算机辅助工程计算机的分类:1)、根据规模大小分类:巨型机、大型通用机、微型机、工作站、服务器2)、根据用途分类:通用计算机、专用计算机3)、根据计算机处理数据的类型:模拟计算机、数字计算机、数字与模拟计算机计算机科学研究与应用人工智能:研究如何让计算机来完成过去只有人才能做的智能的工作。网格计算:专门针对复杂科学计算的新型计算模式。中间件技术:是介于应用软件和操作系统之间的系统软件。云计算:是分布式计算、网格计算、并行计算、网络存储及虚拟化计算机和网络技术发展融合的产物,或者说是它们的商业实现。
  • C线性链表
    线性链表的概念线性链表是一种数据结构,它由一系列节点组成,每个节点包含两部分:数据域和指针域。数据域存储实际数据,而指针域存储指向下一个节点的地址,也称为后继节点。线性链表中的节点在内存中并不需要连续存储,而是通过指针相互连接形成一个逻辑上的连续序列线性链表的特点线性链表的主要特点包括:动态性:线性链表的存储空间可以根据需要动态地分配和释放,这使得链表的长度可以随时改变。非连续性:线性链表中的节点在内存中可以分散存储,不需要像数组那样连续排列。访问特性:在链表中访问特定元素通常需要从头节点开始遍历,因此访问效率不如数组。插入和删除效率:在链表中插入或删除元素通常只需要修改相应的指针,而不需要移动其他元素,因此在某些情况下比数组更高效。线性链表的实现线性链表可以通过编程语言提供的各种数据类型和结构来实现。例如,在C++中,可以通过结构体和指针来实现链表节点和链表本身。链表节点通常定义为一个结构体,其中包含了数据和指向下一个节点的指针。链表本身则可以通过一个指向头节点的指针来实现线性链表的应用线性链表广泛应用于各种场景,尤其是在需要频繁插入和删除操作的数据结构中。例如,它可以用来实现动态数组、栈、队列等数据结构。在这些应用中,链表的动态性和灵活性使其能够有效地管理数据元素的增删操作。注意事项在使用线性链表时,需要注意内存管理和指针操作的正确性。错误的指针操作可能会导致内存泄漏或程序崩溃。此外,由于链表不支持随机访问,访问特定元素通常需要从头节点开始遍历,这可能影响性能。综上所述,线性链表是一种基本且重要的数据结构,它在许多编程问题中都有应用。了解其特性和实现方法对于掌握数据结构和算法的基础知识至关重要。已知非空线性链表第1个链结点指针为list,链结点构造为struct node{datatype data;node *link;};请写一算法,将该链表中数据域值最大的那个点移到链表的最后面。(假设链表中数据域值最大的链结点惟一)(注意:要求先写出算法的解题思路,然后再写出算法)【输入形式】输入为一个整数序列,整数之间以空格隔开,序列以回车结尾。【输出形式】输出为移动后的整数序列,整数之间以空格隔开,序列以回车结尾。【样例输入】312 4951【样例输出】3495112【样例说明】将序列中最大的数字12移动到序列最后。【评分标准】本题必须采用链表来实现移动操作,其他方法不得分。#include <stdio.h>#include <stdlib.h>struct Node { int data; struct Node* next;};int main(){ struct Node* head, *tempHead; int data; char flag; head = (struct Node*)malloc(sizeof(struct Node)); scanf("%d", &data); head->data = data; flag = getchar(); head->next = NULL; tempHead = head; while (flag != '\n') { scanf("%d", &data); flag = getchar(); tempHead->next = (struct Node*)malloc(sizeof(struct Node)); tempHead = tempHead->next; tempHead->data = data; tempHead->next = NULL; } struct Node* maxPtr, *endPtr; int maxData = head->data; maxPtr = endPtr = head; while (endPtr->next != NULL) { endPtr = endPtr->next; if (endPtr->data > maxData) { maxData = endPtr->data; maxPtr = endPtr; } } data = maxPtr->data; maxPtr->data = endPtr->data; endPtr->data = data; tempHead = head; while (tempHead != NULL) { printf("%d ", tempHead->data); tempHead = tempHead->next; } return 0;
总条数:240 到第
上滑加载中