爬虫日常-12306自动购票程序

news2024/11/19 9:34:41

文章目录

  • 前言
  • 页面分析
  • 代码设计

前言

hello兄弟们,最近在钻研新鲜知识,一不留神没想起来更新。今天我们顺着前面几篇文章完整的写出一篇12306的自动购票软件。
在这里插入图片描述
首先把我们已经写完的前期步骤代码再顺一遍

from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


# 定义登录方法
def login(user, pwd):
    login_choice = web.find_element(By.XPATH, '//*[@id="toolbar_Div"]/div[2]/div[2]/ul/li[1]')
    # 点击账号密码登录方式
    login_choice.click()
    username = web.find_element(By.XPATH, '//*[@id="J-userName"]')  # 向账号框传入账号信息
    passwd = web.find_element(By.XPATH, '//*[@id="J-password"]')  # 向密码框传入密码
    username.click()
    username.send_keys(user)
    passwd.click()
    passwd.send_keys(pwd)
    # 定位到登录按钮并点击
    web.find_element(By.XPATH, '//*[@id="J-login"]').click()
    # 设置显示等待直到滑块的span标签被定位到
    WebDriverWait(web, 0.5, 0.05).until(EC.presence_of_element_located((By.ID, 'nc_1_n1z')))
    span = web.find_element(By.ID, 'nc_1_n1z')
    action = ActionChains(web)
    action.click_and_hold(span).move_by_offset(300, 0).perform() # click_and_hold代表点击并保持点击动作。move_by_offset(x, y),其中x代表水平移动距离,y代表垂直移动距离


if __name__ == '__main__':
    opt = Options()
    opt.add_experimental_option('excludeSwitches', ['enable-automation'])  # 去除浏览器顶部显示受自动化程序控制
    opt.add_experimental_option('detach', True)  # 规避程序运行完自动退出浏览器
    web = Chrome(options=opt)
    web.get('https://kyfw.12306.cn/otn/resources/login.html')
    # 解除浏览器特征识别selenium
    script = 'Object.defineProperty(navigator,"webdriver", {get: () => false,});'
    web.execute_script(script)
    user = ''  # 此处输入账号
    pwd = ''   # 此处输入密码
    login(user, pwd)

在前面几篇文章中,我们实现了自动打开浏览器并且完成登录以及绕过验证码操作。
完成这些步骤后,我们应该想到要进行购票操作。老样子,先对登录成功后的页面进行分析在设计代码。

页面分析

在这里插入图片描述可以看到登录成功后映入眼帘的就是登录成功的信息以及左侧一系列的功能选项。屏幕中央也有一个车票预定的跳转选项,点击后会跳转到车票查询页面
在这里插入图片描述
可以看到页面上有出发地,目的地,出发日三个输入框。这里就是我们需要传入参数的地方,先随便传入参数看看页面返回数据。
在这里插入图片描述在输入参数时我发现简单的输入数据并不能把参数输入到框中,必须在输入参数后enter确认后,输入框的信息才会变实,此时才能正确查询。否则点击查询时页面输入框变红报错
在这里插入图片描述只有正确输入参数后才会显示可选车辆信息
在这里插入图片描述
到了这一步后就是选择自己想要选择的车次点击选票了​
大致流程分析到这里就可以开始设计代码了

代码设计

首先完成第一步点击车票查询按钮,最好在这一步完成参数传递,所以我们设计一个带有出发地,目的地,出发日期三个参数的函数

def get_ticket_info(start_city, end_city, date):
		pass

首先我们需要在main中定义完start_city,end_city,date三个参数并自己赋值

if __name__ == '__main__':
	start_city = '常州' # 输入自己的出发地
	end_city = '丹阳' # 目的地
	date = '2023-04-21' # 按照页面规定格式输入出发日期
	get_ticket_info(start_city, end_city, date)

参数定义完成后我们就要开始设计get_ticket_info内部的代码了
在这里插入图片描述

# 首先第一步,定位到登录后页面的车票预定链接并点击进去,
# 上图可以看到我们能够通过其id定位到
web.find_element(By.ID, 'link_for_ticket').click()

我们整合这一步并运行查看效果(基于上面登录代码后新加代码内容)

def get_ticket_info(start_city, end_city, date):
    web.find_element(By.ID, 'link_for_ticket').click()​
​
if __name__ == '__main__':
    start_city = '常州'
    end_city = '丹阳'
    date = '2023-04-21'
    get_ticket_info(start_city, end_city, date)

在这里插入图片描述可以看到如上图所示的报错信息,没有检测到我们的element信息,原因同样是因为没有给页面反应时间就直接请求,我们需要再请求发送前设计一个显示等待

def get_ticket_info(start_city, end_city, date):
		# 通过检测xpath路径是否变更为要选择的id
	WebDriverWait(web, 2, 0.5).until(EC.presence_of_element_located((By.ID, 'link_for_ticket')))
    web.find_element(By.ID, 'link_for_ticket').click()

在这里插入图片描述可以看到我们成功进入到了车票预定界面。
接下来就是定位到输入框并传入参数

from selenium.webdriver.common.keys import Keys
def get_ticket_info(start_city, end_city, date):
    WebDriverWait(web, 2, 0.5).until(EC.presence_of_element_located((By.ID, 'link_for_ticket')))
    web.find_element(By.ID, 'link_for_ticket').click()

    web.find_element(By.ID, 'fromStationText').click()  # 先定位到出发地输入框点击后再传入参数
    web.find_element(By.ID, 'fromStationText').send_keys(start_city, Keys.ENTER)  # Keys库可以模拟实现键盘上的功能键

    web.find_element(By.ID, 'toStationText').click()  # 目的地
    web.find_element(By.ID, 'toStationText').send_keys(end_city, Keys.ENTER)

    web.find_element(By.ID, 'train_date').clear()  # 由于date页面默认当天日期,所以先清空默认内容在输入参数
    web.find_element(By.ID, 'train_date').send_keys(date, Keys.ENTER)

    web.find_element(By.ID, 'query_ticket').click()  # 点击查询

运行查看效果
在这里插入图片描述完美实现我们设计的步骤
到了这一步后我们可以将页面上的所以车次信息获取打印到控制台中让我们选择车次。
在这里插入图片描述​可以看到右边一列tr就是我们要获取到的信息保存地,可我们同样注意到并不是tr都带有列表信息,我们先尝试利用etree的xpath获取到此处的列表

def get_ticket_list():
    # 一定要用显示等待,否则会返回空列表
    WebDriverWait(web,2,0.5).until(EC.presence_of_element_located((By.XPATH, '//*[@id="queryLeftTable"]/tr')))
    tree = etree.HTML(web.page_source)
    tick_list = tree.xpath('//*[@id="queryLeftTable"]/tr')
    print(tick_list)

在这里插入图片描述可以看到所有tr信息已经获取。这个时候就可以对信息进一步提取。由于tr只有一半是包含具体信息的所以我们需要做一个过滤,利用if判断能否获取到列车车次文本信息,能获取的就保留,获取不到的就剔除

def get_ticket_info():
    WebDriverWait(web, 2, 0.5).until(EC.presence_of_element_located((By.XPATH, '//*[@id="queryLeftTable"]/tr')))
    tree = etree.HTML(web.page_source)
    tick_list = tree.xpath('//*[@id="queryLeftTable"]/tr')
    tr_dic = {}
    for tr in tick_list:
        if not tr.xpath('./td[1]/div/div[1]/div/a/text()'):
            continue
        else:
            tr_num = '车次' + tr.xpath('./td[1]/div/div[1]/div/a/text()')[0]
            tr_id = '车辆ID为:' + tr.xpath('./@id')[0] + '|'  # 添加标识头和分隔符便于观看
            tr_from_place = '出发地:' + tr.xpath('./td[1]/div/div[2]/strong[1]/text()')[0] + '  '
            tr_get_place = '目的地:' + tr.xpath('./td[1]/div/div[2]/strong[2]/text()')[0] + '  '
            tr_start_time = '出发时间:' + tr.xpath('./td[1]/div/div[3]/strong[1]/text()')[0] + '  '  # 列车发动时间
            tr_get_time = '到达时间:' + tr.xpath('./td[1]/div/div[3]/strong[2]/text()')[0] + '  '  # 列车到达目的地时间
            if not tr.xpath('./td[2]/@aria-label'):
                tr_shang_wu = 'Null'
            else:
                tr_shang_wu = '商务座:' + tr.xpath('./td[2]/@aria-label')[0] + '  '  # 商务座
            if not tr.xpath('./td[3]/@aria-label'):
                tr_yi_deng = 'Null'
            else:
                tr_yi_deng = '一等座:' + tr.xpath('./td[3]/@aria-label')[0] + '  '  # 一等座
            if not tr.xpath('./td[4]/@aria-label'):
                tr_er_deng = 'Null'
            else:
                tr_er_deng = '二等:' + tr.xpath('./td[4]/@aria-label')[0] + '  '  # 二等座
            if not tr.xpath('./td[6]/@aria-label'):
                tr_ruan_wo = 'Null'
            else:
                tr_ruan_wo = '软卧:' + tr.xpath('./td[6]/@aria-label')[0] + '  '  # 软卧
            if not tr.xpath('./td[8]/@aria-label'):
                tr_ying_wo = 'Null'
            else:
                tr_ying_wo = '硬卧:' + tr.xpath('./td[8]/@aria-label')[0] + ' '   # 硬卧
            if not tr.xpath('./td[10]/@aria-label'):
                tr_ying_zuo = 'Null'
            else:
                tr_ying_zuo = '硬座:' + tr.xpath('./td[10]/@aria-label')[0] + ' '  # 硬座
            if not tr.xpath('./td[11]/@aria-label'):
                tr_wu_zuo = 'Null'
            else:
                tr_wu_zuo = '无座:' + tr.xpath('./td[11]/@aria-label')[0]  # 无座
            tr_dic[tr_num] = tr_id + tr_from_place + tr_get_place + tr_start_time + tr_get_time + tr_shang_wu + \
                            tr_yi_deng + tr_er_deng + tr_ruan_wo + tr_ying_wo + tr_ying_zuo + tr_wu_zuo
    return tr_dic

获取到车次信息后,我们就要设计选择函数。首先将获取到的信息规范输出在控制台中,然后根据输入的自己想要选择的车次信息进行匹配获取到车辆id进行预定行为​

def chick_ticket(dic):
    print('*'*15+'查询到的车次信息如下'+'*'*30)
    print(str(dic).replace(',', '\n'))
    train_id = '车次:' + str(input('请输入选择的车次:\n'))  # 车次:与输入的车次num拼接为字典的key值
    if train_id in dic.keys():
        tr_info = dic.get(train_id)  # 根据key值信息获取到其保存在value里的id与座位信息等
    obj = re.compile(r'车辆ID为:(?P<id>.*?)出发地')  # 利用正则获取到车次id
    result = obj.finditer(tr_info)  # 此时获取到的是迭代器,要重新获取出来
    for i in result:
        tr_id = i.group('id').strip('|')  # 由于获取到的id中带有分隔符|,因此剔除掉
    web.find_element(By.XPATH, f'//*[@id="{tr_id}"]/td[13]/a').click()  # 根据id匹配到车次所在列并点击末尾的预定按钮

运行程序查看效果
在这里插入图片描述在这里插入图片描述可以看到页面成功匹配选择的车辆并跳转到购票页面​
到了这一步后,后面的内容就是要根据你自己的乘车人的数量,以及成人票与学生票的选择,再加上一个座位匹配模块就可以完成了。
这一块的内容我的源码是设计完了,但是根据我的个人需求设计的。建议小伙伴们自己动手完成这最后一个模块的设计,如果想要这一块源码的话,可以评论,我会考虑下次把这一块补上。关于12306的订票就先写这么多了。希望兄弟们勤加练习。
在这里插入图片描述
最后放上本文章的源码

from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from lxml import etree
import re


# 定义登录方法
def login(user, pwd):
    login_choice = web.find_element(By.XPATH, '//*[@id="toolbar_Div"]/div[2]/div[2]/ul/li[1]')
    # 点击账号密码登录方式
    login_choice.click()
    username = web.find_element(By.XPATH, '//*[@id="J-userName"]')  # 向账号框传入账号信息
    passwd = web.find_element(By.XPATH, '//*[@id="J-password"]')  # 向密码框传入密码
    username.click()
    username.send_keys(user)
    passwd.click()
    passwd.send_keys(pwd)
    # 定位到登录按钮并点击
    web.find_element(By.XPATH, '//*[@id="J-login"]').click()
    # 设置显示等待直到滑块的span标签被定位到
    WebDriverWait(web, 0.5, 0.05).until(EC.presence_of_element_located((By.ID, 'nc_1_n1z')))
    span = web.find_element(By.ID, 'nc_1_n1z')
    action = ActionChains(web)
    action.click_and_hold(span).move_by_offset(300, 0).perform() # click_and_hold代表点击并保持点击动作。move_by_offset(x, y),其中x代表水平移动距离,y代表垂直移动距离


def get_ticket_info(start_city, end_city, date):
    WebDriverWait(web, 2, 0.5).until(EC.presence_of_element_located((By.ID, 'link_for_ticket')))
    web.find_element(By.ID, 'link_for_ticket').click()

    web.find_element(By.ID, 'fromStationText').click()  # 先定位到出发地输入框点击后再传入参数
    web.find_element(By.ID, 'fromStationText').send_keys(start_city, Keys.ENTER)  # Keys库可以模拟实现键盘上的功能键

    web.find_element(By.ID, 'toStationText').click()  # 目的地
    web.find_element(By.ID, 'toStationText').send_keys(end_city, Keys.ENTER)

    web.find_element(By.ID, 'train_date').clear()  # 由于date页面默认当天日期,所以先清空默认内容在输入参数
    web.find_element(By.ID, 'train_date').send_keys(date, Keys.ENTER)

    web.find_element(By.ID, 'query_ticket').click()  # 点击查询


def get_ticket_dic_info():
    WebDriverWait(web, 2, 0.5).until(EC.presence_of_element_located((By.XPATH, '//*[@id="queryLeftTable"]/tr')))
    tree = etree.HTML(web.page_source)
    tick_list = tree.xpath('//*[@id="queryLeftTable"]/tr')
    tr_dic = {}
    for tr in tick_list:
        if not tr.xpath('./td[1]/div/div[1]/div/a/text()'):
            continue
        else:
            tr_num = '车次:' + tr.xpath('./td[1]/div/div[1]/div/a/text()')[0]
            tr_id = '车辆ID为:' + tr.xpath('./@id')[0] + '|'  # 添加标识头和分隔符便于观看
            tr_from_place = '出发地:' + tr.xpath('./td[1]/div/div[2]/strong[1]/text()')[0] + '  '
            tr_get_place = '目的地:' + tr.xpath('./td[1]/div/div[2]/strong[2]/text()')[0] + '  '
            tr_start_time = '出发时间:' + tr.xpath('./td[1]/div/div[3]/strong[1]/text()')[0] + '  '  # 列车发动时间
            tr_get_time = '到达时间:' + tr.xpath('./td[1]/div/div[3]/strong[2]/text()')[0] + '  '  # 列车到达目的地时间
            if not tr.xpath('./td[2]/@aria-label'):
                tr_shang_wu = 'Null'
            else:
                tr_shang_wu = '商务座:' + tr.xpath('./td[2]/@aria-label')[0] + '  '  # 商务座
            if not tr.xpath('./td[3]/@aria-label'):
                tr_yi_deng = 'Null'
            else:
                tr_yi_deng = '一等座:' + tr.xpath('./td[3]/@aria-label')[0] + '  '  # 一等座
            if not tr.xpath('./td[4]/@aria-label'):
                tr_er_deng = 'Null'
            else:
                tr_er_deng = '二等:' + tr.xpath('./td[4]/@aria-label')[0] + '  '  # 二等座
            if not tr.xpath('./td[6]/@aria-label'):
                tr_ruan_wo = 'Null'
            else:
                tr_ruan_wo = '软卧:' + tr.xpath('./td[6]/@aria-label')[0] + '  '  # 软卧
            if not tr.xpath('./td[8]/@aria-label'):
                tr_ying_wo = 'Null'
            else:
                tr_ying_wo = '硬卧:' + tr.xpath('./td[8]/@aria-label')[0] + ' '   # 硬卧
            if not tr.xpath('./td[10]/@aria-label'):
                tr_ying_zuo = 'Null'
            else:
                tr_ying_zuo = '硬座:' + tr.xpath('./td[10]/@aria-label')[0] + ' '  # 硬座
            if not tr.xpath('./td[11]/@aria-label'):
                tr_wu_zuo = 'Null'
            else:
                tr_wu_zuo = '无座:' + tr.xpath('./td[11]/@aria-label')[0]  # 无座
            tr_dic[tr_num] = tr_id + tr_from_place + tr_get_place + tr_start_time + tr_get_time + tr_shang_wu + \
                            tr_yi_deng + tr_er_deng + tr_ruan_wo + tr_ying_wo + tr_ying_zuo + tr_wu_zuo
    return tr_dic


def chick_ticket(dic):
    print('*'*15+'查询到的车次信息如下'+'*'*30)
    print(str(dic).replace(',', '\n'))
    train_id = '车次:' + str(input('请输入选择的车次:\n'))  # 车次:与输入的车次num拼接为字典的key值
    if train_id in dic.keys():
        tr_info = dic.get(train_id)  # 根据key值信息获取到其保存在value里的id与座位信息等
    obj = re.compile(r'车辆ID为:(?P<id>.*?)出发地')  # 利用正则获取到车次id
    result = obj.finditer(tr_info)  # 此时获取到的是迭代器,要重新获取出来
    for i in result:
        tr_id = i.group('id').strip('|')  # 由于获取到的id中带有分隔符|,因此剔除掉
    web.find_element(By.XPATH, f'//*[@id="{tr_id}"]/td[13]/a').click()  # 根据id匹配到车次所在列并点击末尾的预定按钮


if __name__ == '__main__':
    opt = Options()
    opt.add_experimental_option('excludeSwitches', ['enable-automation'])  # 去除浏览器顶部显示受自动化程序控制
    opt.add_experimental_option('detach', True)  # 规避程序运行完自动退出浏览器
    web = Chrome(options=opt)
    web.get('https://kyfw.12306.cn/otn/resources/login.html')
    # 解除浏览器特征识别selenium
    script = 'Object.defineProperty(navigator,"webdriver", {get: () => false,});'
    web.execute_script(script)
    user = ''  # 此处输入账号
    pwd = ''   # 此处输入密码
    login(user, pwd)
    start_city = ''
    end_city = ''
    date = ''
    get_ticket_info(start_city, end_city, date)
    tick_dic = get_ticket_dic_info()
    chick_ticket(tick_dic)

ok,下次再见,记得点赞兄弟们
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/444789.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

阿里大佬都在熬夜肝的Java程序优化笔记,程序性能提高了5倍!

前言 此笔记从软件设计、编码和JVM等维度阐述性能优化的方法和技巧&#xff0c;分享资深架构师Java程序性能优化的宝贵经验&#xff0c;专注于Java应用程序的优化方法、技巧和思想&#xff0c;并深度剖析JDK部分的实现。具有较强的层次性和连贯性&#xff0c;深入剖析软件设计…

Word控件Spire.Doc 【脚注】教程(5):单词脚注的位置与数字格式

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

1.19 从0开始学习Unity游戏开发--扩展编辑器

在之前的篇章里面&#xff0c;我们一直在编辑器里面干活&#xff0c;然后做好资源的编辑和代码开发后&#xff0c;我们可以直接在编辑器内点击那个播放按钮就能真实的把游戏跑起来&#xff0c;但是有时候&#xff0c;我们可能希望在菜单里面加个按钮&#xff0c;这样我们可以直…

C++ STL学习之【容器适配器】

✨个人主页&#xff1a; 夜 默 &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f38a;每篇一句&#xff1a; 图片来源 A year from now you may wish you had started today. 明年今日&#xff0c;你会希望此时此刻的自己已经开始行动了。 文章目录 &#x1f307;前言&a…

内存泄漏动态检测(valgrind)

初步判断是否有泄漏 Linux 内存性能优化 —— 高内存使用及内存泄漏排查 比如该文的介绍&#xff0c;需要初步了解top free -h等命令&#xff1b; 主要看free 内存泄漏检测方法&#xff1a; 静态我常用的是cppcheck&#xff1b; 动态的 Linux下内存泄漏定位方法 这个文章…

Node.js 一:基础

1.node.js是什么&#xff1a; 2.node.js的作用&#xff1a; 1.服务器应用&#xff1a;b站.. 2.开发工具类应用&#xff1a;webpack&#xff0c;bable等等 3.桌面端应用&#xff1a;vscode&#xff0c;postman等 这些应用都是基于electron框架开发&#xff0c;electron基于node…

【设计模式】23种设计模式之行为型模式

一、模板方法模式 1、豆浆制作问题 编写制作豆浆的程序&#xff0c;说明如下: 1&#xff09;、制作豆浆的流程 选材--->添加配料--->浸泡--->放到豆浆机打碎 2&#xff09;、通过添加不同的配料&#xff0c;可以制作出不同口味的豆浆 3&#xff09;、选材、浸泡和放…

拥抱还是革命,ChatGPT时代 AI专家给出15条科研生存之道

来源&#xff1a;专知 微信号&#xff1a;Quan_Zhuanzhi 你是学术机构的人工智能研究员吗?你是否担心自己无法应对当前人工智能的发展步伐?您是否觉得您没有(或非常有限)访问人工智能研究突破所需的计算和人力资源?你并不孤单; 我们有同样的感觉。越来越多的人工智能学者不…

vuepress-yarn-nodes-静态网页_个人博客搭建

nodes官网&#xff1a;https://nodejs.org/en 先下载nodes进行安装&#xff0c;一般nodes会自带包管理器npm&#xff0c;注意npm与nodes的对应关系&#xff0c;除了npm之外还有yarn包管理器&#xff0c;一般会用npm安装这个包 npm install --global yarnnpm降低版本的方法 np…

LeetCode 1026. 节点与其祖先之间的最大差值

【LetMeFly】1026.节点与其祖先之间的最大差值 力扣题目链接&#xff1a;https://leetcode.cn/problems/maximum-difference-between-node-and-ancestor/ 给定二叉树的根节点 root&#xff0c;找出存在于 不同 节点 A 和 B 之间的最大值 V&#xff0c;其中 V |A.val - B.val…

《花雕学AI》24:如何用万能Prompt公式与ChatGPT进行高效的对话测试

引言 你是否想要与人工智能进行有趣、有价值、有说服力的对话&#xff1f;你是否想要使用ChatGPT这个强大而灵活的对话生成器来创造出任何类型和主题的对话&#xff1f;如果是这样&#xff0c;那么你需要了解一个简单而强大的工具&#xff0c;就是万能Prompt公式。 万能Promp…

微软office认证课程

感谢阅读 非原创声明&#xff0c;根据微软课程学习理解而已Get started with Microsoft 365Work Smarter with Microsoft Word与 Microsoft Word 更加智能地工作Microsoft 365 SubscriptionsMicrosoft 365 订阅个人补充Exercise: Finding Help and changing account settings练…

cpp 程序与 c 程序的相互调用(extern “C“ 的使用)

实际在编译的过程中&#xff0c;.cpp 文件调用 .c文件中的函数会出错。假设代码结构如下&#xff1a; 目录 一、编译过程分析 1、预处理 2、编译 3、汇编 4、链接 二、问题解决 1、解决方案 2、解决思路 一、编译过程分析 1、预处理 该阶段头文件会被展开&#xff0c…

FPGA学习笔记(二):时序逻辑之计数器

与组合逻辑&#xff08;给定输入&#xff0c;输出是确定的&#xff0c;与时间无关&#xff09;相比较&#xff0c;时序逻辑不仅仅与输入信号相关&#xff0c;还与时钟信号相关。 D触发器&#xff1a;在上升沿时&#xff08;CLK&#xff09;才将输出&#xff08;Q&#xff09;修…

Failed to load property source from location ‘classpath:/application.yaml‘

问题 项目起动时&#xff0c;找不到yaml&#xff0c;各种处理还是没有解决&#xff0c;比如&#xff0c;clean&#xff0c;重启电脑&#xff0c;检查utf8等。 同事拉的新代码又是正常可以跑&#xff0c;这就有点奇怪了。 11:07:39.682 [main] ERROR org.springframework.boot.…

【19】linux进阶——后台运行()和nohup命令

大家好&#xff0c;这里是天亮之前ict&#xff0c;本人网络工程大三在读小学生&#xff0c;拥有锐捷的ie和红帽的ce认证。每天更新一个linux进阶的小知识&#xff0c;希望能提高自己的技术的同时&#xff0c;也可以帮助到大家 另外其它专栏请关注&#xff1a; 锐捷数通实验&…

分享自己接私活常用的开源系统

目前开源系统是JNPF框架。技术栈上是SpringBoot、SpringCloud、Spring Web、MyBatis、Swagger、Vue、Element。 这些都是比较主流的技术&#xff0c;无论是技术层面的先进性还是学习难度都是比较低的&#xff0c;目前网络上有大量可供参考学习的资料。 并且它支持前后端分离和…

Ceph入门到精通-Ceph如何扩展到超过十亿个对象?

Ceph如何扩展到超过十亿个对象&#xff1f;-ceph部署多少个节点 (51cto.com) 越来越多的组织被要求管理数十亿个文件和几百上千PB的数据。无论是在公共云还是本地环境中&#xff0c;Ceph对象存储都是值得考虑的一个选项。本篇文章将通过七部分的精选内容为下面这些问题提供答案…

vue3+echarts实现世界地图以及轨线(label使用fomatter+rich动态添加图片及背景色,以及label如何添加动态边框色)

背景 最近项目开发&#xff0c;需要开发一个世界地图&#xff0c;并且实现经纬度对应的点对点轨线动效&#xff0c;效果如下&#xff1a; 问题 如何在刚打开页面的时候就显示地点名称label如何同时添加图片和背景色label怎么动态修改字体颜色及图片以及动态边框色添加动效及…

YumRepo Error: All mirror URLs are not using ftp, http[s] or file解决办法

文章目录 一、问题背景二、问题原因三、解决方法 一、问题背景 CentOS6.5利用yum -y install gcc命令安装程序报错YumRepo Error: All mirror URLs are not using ftp, http[s] or file.Eg. Invalid release/repo/arch combination/ removing mirrorlist with no valid mirror…