UI界面自动化BagePage

常用basepage模块代码

# -*- coding: utf-8 -*-
# @Desc: UI自动化测试的一些基础浏览器操作方法# 第三方库导入
import time
from logging import config
import randomimport allure
from selenium.webdriver.common.alert import Alert
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.select import Selectimport config
from common.utils.ReturnTime import ReturnTime
from jc_log.setting import get_logger
import pyautogui
from pywinauto.keyboard import send_keys
from selenium.common.exceptions import NoSuchElementException, InvalidSelectorException, TimeoutException
from selenium.webdriver import ActionChains
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWaitlogger = get_logger(__name__)
g_timeout = 10
g_poll_frequency = 0.2class BasePage:"""UI自动化基础操作封装"""def __init__(self, driver):self.driver = driverself.__img_dir = config.REPORT_DIRdef refresh(self):"""刷新网页"""self.driver.refresh()def get_url(self, url):"""访问指定地址"""self.driver.get(url=url)return self.driver.current_urldef get_current_url(self):"""获取当前浏览器驱动的地址"""return self.driver.current_urldef force_click(self, locator: tuple, mode: str = "click", force=False):"""鼠标点击,当元素不可点击的时候,使用强制点击:param locator: 元素定位,元祖类型:param mode: visible(元素可见),notvisible(元素消失不可见), exist(元素存在),click(元素可点击):param force: 强制点击,默认false"""try:elem = self.find_element(locator=locator, mode=mode)if not force:self.driver.execute_script("arguments[0].click()", elem)else:elem.click()self.driver.execute_script("arguments[0].click({force: true})", elem)except Exception as e:print("未找到元素:{}".format(e))raise edef wait_element_visibility(self, locator: tuple, timeout=20, poll_frequency=g_poll_frequency):"""显性等待: 等待元素可见:param locator: 元素定位,元祖类型:param timeout:param poll_frequency:return:"""page = self.get_current_url()logger.debug(f"-开始-等待页面{page}的元素:{locator}可见")try:# 获取等待开始时间的时间戳__start_time = ReturnTime.get_timestamp()rtn = WebDriverWait(self.driver, timeout, poll_frequency).until(ec.visibility_of_element_located(locator))# 计算元素等待的时间__wait_time = ReturnTime.get_timestamp() - __start_timelogger.debug(f"页面:{page}上的元素{locator}已可见,共计等待{__wait_time:0.2f}秒")except TimeoutException:logger.error(f"页面:{page},等待元素{locator}超时")self.set_error_img()raise TimeoutException('元素等待超时')except InvalidSelectorException as e:logger.error(f"页面:{page},元素不可见或定位表达式:{locator}异常\n {e}")raise InvalidSelectorException('元素定位异常')return rtndef wait_element_clickable(self, locator: tuple, timeout=g_timeout, poll_frequency=g_poll_frequency):"""显性等待: 等待元素可点击:param locator: 元素定位,元祖类型:param timeout::param poll_frequency:return:"""page = self.get_current_url()logger.debug(f"-开始-等待页面{page}的元素:{locator}可点击")try:# 获取等待开始时间的时间戳__start_time = ReturnTime.get_timestamp()rtn = WebDriverWait(self.driver, timeout, poll_frequency).until(ec.element_to_be_clickable(locator))# 计算元素等待的时间__wait_time = ReturnTime.get_timestamp() - __start_timelogger.debug(f"页面:{page}上的元素{locator}已可点击,共计等待{__wait_time:0.2f}秒")except TimeoutException as e:logger.error(f"页面:{page},等待元素{locator}超时")self.set_error_img()raise eexcept InvalidSelectorException as e:logger.error(f"页面:{page},元素不可点击或定位表达式:{locator}异常\n {e}")raise ereturn rtndef wait_element_presence(self, locator: tuple, timeout=g_timeout, poll_frequency=g_poll_frequency):"""显性等待: 等待元素被加载出来:param locator: 元素定位,元祖类型:param timeout:param poll_frequency:return:"""page = self.get_current_url()logger.debug(f"-开始-等待页面{page}的元素:{locator}存在")try:# 获取等待开始时间的时间戳__start_time = ReturnTime.get_timestamp()rtn = WebDriverWait(self.driver, timeout, poll_frequency).until(ec.presence_of_all_elements_located(locator))# 计算元素等待的时间__wait_time = ReturnTime.get_timestamp() - __start_timelogger.debug(f"页面:{page}上的元素{locator}已存在,共计等待{__wait_time:0.2f}秒")except TimeoutException as e:logger.error(f"页面:{page},等待元素{locator}超时")self.set_error_img()raise eexcept InvalidSelectorException as e:logger.error(f"页面:{page},元素不存在或定位表达式:{locator}异常\n {e}")raise ereturn rtndef wait_element_not_visible(self, locator: tuple, timeout=g_timeout, poll_frequency=g_poll_frequency):"""等待元素不可见:param locator: 元素定位表达式:param timeout:param poll_frequency:return::return: 无返回值"""page = self.get_current_url()logger.debug(f"-开始-等待页面{page}的元素:{locator}存在")try:# 获取等待开始时间的时间戳__start_time = ReturnTime.get_timestamp()time.sleep(1)rtn = WebDriverWait(self.driver, timeout, poll_frequency).until(ec.invisibility_of_element_located(locator))# 计算元素等待的时间__wait_time = ReturnTime.get_timestamp() - __start_timelogger.debug(f"页面:{page}上的元素{locator}已经不可见,共计等待{__wait_time:0.2f}秒")except TimeoutException as e:logger.error(f"页面:{page},等待元素{locator}不可见超时")self.set_error_img()raise eexcept InvalidSelectorException as e:logger.error(f"页面:{page},元素不存在或定位表达式:{locator}异常\n {e}")raise ereturn rtndef get_element_attribute(self, locator: tuple, attr_name):"""获取元素属性值:param locator: 元素定位,元祖类型:param attr_name:return: 元素属性值"""try:return self.driver.find_element(*locator).get_attribute(attr_name)except NoSuchElementException as e:print("未找到元素:{}".format(e))raise edef get_name(self, locator: tuple):"""获取元素的name属性值"""return self.get_element_attribute(locator, "name")def get_title(self, locator: tuple):"""获取元素的title属性值"""return self.get_element_attribute(locator, "title")def get_class(self, locator: tuple):"""获取元素的class属性值"""return self.get_element_attribute(locator, "class")def switch_to_frame(self, reference=None, timeout=g_timeout, poll=g_poll_frequency):"""iframe切换:param reference: 可以是id, name,索引或者元素定位(元祖):param timeout::param poll::return:"""if not reference:return self.driver.switch_to.default_content()return WebDriverWait(self.driver, timeout, poll).until(ec.frame_to_be_available_and_switch_to_it(reference))def __get_title_handle(self, title):handles = self.driver.window_handlesfor handle in handles:self.driver.switch_to.window(handle)if self.driver.title == title:return handledef switch_to_window(self, title):"""切换到指定窗口"""self.__get_title_handle(title)return selfdef switch_next_window(self):"""切换到另一个窗口"""# 获取所有的窗口windows = self.driver.window_handlesif len(windows) >= 2:# 切换窗口self.driver.switch_to.window(self.driver.window_handles[-1])return selfdef open_new_window(self, url):"""打开一个新窗口"""# 获取所有的窗口start_window = self.driver.window_handls# 打开新窗口js = "window.open({})".format(url)self.driver.execute_script(js)# 等待新窗口出现,进行切换WebDriverWait(self.driver, 5, 0.5).until(ec.new_window_is_opened(start_window))# 切换窗口self.driver.switch_to.window(self.driver.window_handls[-1])return selfdef __select_wait_method(self, locator: tuple, mode: str = "visible") -> None:"""选择元素定位的等待方式:param locator: 元素的定位表达式 例:(By.xx,'定位表达式'):param mode: visible(元素可见), exist(元素存在),click(元素可点击):return: 无返回值"""page = self.get_current_url()if mode == "visible":self.wait_element_visibility(locator=locator)elif mode == "exist":self.wait_element_presence(locator=locator)elif mode == "click":self.wait_element_clickable(locator=locator)else:logger.error(f"定位{page}页面的元素:{locator},mode参数传值异常,入参值为:{mode}")def find_element(self, locator: tuple, mode: str = "visible") -> WebElement:"""定位元素,支持所有定位单个元素的定位表达式:param locator: 元素的定位表达式 例:(By.xx,'定位表达式'):param mode: visible(元素可见), exist(元素存在),click(元素可点击):return: 定位到的元素对象"""page = self.get_current_url()self.__select_wait_method(locator=locator, mode=mode)try:logger.debug(f"正在定位{page}页面的: {locator} 的元素")element = self.driver.find_element(*locator)self.element_dyeing(element=element)return elementexcept TimeoutException:logger.error(f"页面:{page},定位元素:{locator}定位超时")self.set_error_img()raise TimeoutException("元素定位超时请检查")except Exception:logger.error(f"页面:{page},定位元素:{locator}定位失败")self.set_error_img()raise Exception("元素定位失败请检查")def find_elements(self, locator: tuple, mode: str = "visible") -> list:"""定位一组元素,返回一个列表:param locator: 元素的定位表达式 例:(By.xx,'定位表达式'):param mode: visible(元素可见),notvisible(元素消失不可见), exist(元素存在):return: 返回一组元素是一个列表"""page = self.get_current_url()self.__select_wait_method(locator=locator, mode=mode)try:logger.debug(f"正在定位{page}页面的: {locator} 的元素")element_list = self.driver.find_elements(*locator)return element_listexcept NoSuchElementException as e:logger.error(f"页面:{page},定位元素:{locator}定位失败")self.set_error_img()raise edef __move_element_visible(self, locator: tuple, element: WebElement, alignment: bool = False) -> None:"""将元素移动到页面可见区域:param locator: 元素的定位表达式 例:(By.xx,'定位表达式'):param alignment 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐:param element 需要可见的元素:return: 无返回值"""page = self.get_current_url()logger.debug(f'将{page}页面的元素:{locator}移动至浏览器可见区域')try:# 代码执行比页面渲染速度快 这里放0.5秒等待页面渲染time.sleep(0.5)self.driver.execute_script('arguments[0].scrollIntoView({0});'.format(alignment), element)# 休眠1秒让页面可以正常滚动到对应的位置再执行下去time.sleep(1)except Exception as e:logger.error(f"{page}页面的元素:{locator}移动失败\n{e}")self.set_error_img()raise edef click(self, locator: tuple, mode: str = "click", alignment: bool = False, move_element: bool = False,is_double_click: bool = False) -> None:"""点击元素:param locator: 元素的定位表达式 例:(By.xx,'定位表达式'):param mode: visible(元素可见),notvisible(元素消失不可见), exist(元素存在),click(元素可点击):param alignment: 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐:param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用:param is_double_click: False单击元素,传入True 双击元素:return: 无返回值"""page = self.get_current_url()element = self.find_element(locator=locator, mode=mode)if move_element is True:self.__move_element_visible(locator=locator, element=element, alignment=alignment)try:logger.debug(f"点击:{page}页面,属性为{locator}的元素")if is_double_click:ActionChains(self.driver).double_click(element).perform()else:element.click()except Exception as e:logger.error(f"页面{page}的元素: {locator} 点击失败")self.set_error_img()raise edef click_elements(self, locator: tuple, mode: str = "click", alignment: bool = False, move_element: bool = False,is_double_click: bool = False) -> None:"""点击一组元素:param locator: 元素的定位表达式 例:(By.xx,'定位表达式'):param mode: visible(元素可见),notvisible(元素消失不可见), exist(元素存在),click(元素可点击):param alignment: 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐:param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用:param is_double_click: False单击元素,传入True 双击元素:return: 无返回值"""page = self.get_current_url()elements = self.find_elements(locator=locator, mode=mode)if move_element is True:self.__move_element_visible(locator=locator, element=elements[0], alignment=alignment)try:logger.debug(f"点击:{page}页面,属性为{locator}的元素")for element in elements:if is_double_click:ActionChains(self.driver).double_click(element).perform()else:element.click()except Exception as e:logger.error(f"页面{page}的元素: {locator} 点击失败")self.set_error_img()raise edef random_click_element(self, locator: tuple, num: int, mode: str = "click", alignment: bool = False,move_element: bool = False) -> str:"""随机点击一个元素:param locator: 元素的定位表达式 例:(By.xx,'定位表达式'):param num: 从第几位元素开始点击:param mode: visible(元素可见), exist(元素存在),click(元素可点击):param alignment: 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐:param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用:return: 点击的元素的文本"""page = self.get_current_url()elements = self.find_elements(locator=locator, mode=mode)click_num: int = random.randint(num, len(elements) - 1)try:element = elements[click_num]if move_element is True:self.__move_element_visible(locator=locator, element=element, alignment=alignment)self.element_dyeing(element)logger.debug(f"点击:{page}页面,属性为{locator}的元素中的{click_num}位")element.click()except Exception as e:logger.error(f"页面{page}的元素: {locator} 中的第{click_num}位元素点击失败")self.set_error_img()raise ereturn element.textdef input_text(self, locator: tuple, content: str or int, mode: str = "visible", alignment: bool = False,move_element: bool = False) -> WebElement:"""输入文本内容:param locator: 传入元素定位表达式:param content: 传入输入的文本内容:param mode:  visible(元素可见), exist(元素存在):param alignment: 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐:param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用:return: 无返回值"""page = self.get_current_url()element = self.find_element(locator=locator, mode=mode)if move_element is True:self.__move_element_visible(locator=locator, element=element, alignment=alignment)try:self.clear_contents(locator=locator, mode=mode, alignment=alignment)logger.debug(f"输入操作:{page}页面下的属性为:{locator}的元素,输入内容为{content}")element.send_keys(content)self.driver.execute_script("arguments[0].setAttribute('style', 'background: write; border: 1px solid black;');", element)except Exception as e:self.set_error_img()logger.error(f"页面{page}的属性: {locator} 输入操作失败")raise ereturn elementdef clear_contents(self, locator: tuple, mode: str = "visible", alignment: bool = False,move_element: bool = False) -> None:"""清除文本内容:param locator: 传入元素定位表达式:param mode:  visible(元素可见), exist(元素存在):param alignment: 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐:param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用:return: 无返回值"""page = self.get_current_url()element = self.find_element(locator=locator, mode=mode)if move_element is True:self.__move_element_visible(locator=locator, element=element, alignment=alignment)try:logger.debug(f"输入操作:{page}页面下的属性为:{locator}的元素,清除内容")# 保证正常清除time.sleep(0.2)element.clear()except Exception as e:self.set_error_img()logger.error(f"页面{page}的属性: {locator} 清除操作失败")raise edef get_element_text(self, locator: tuple, mode: str = 'visible', alignment: bool = False,move_element: bool = False) -> str:"""获取元素的文本内容:param locator:  传入元素定位表达式:param mode: visible(元素可见), exist(元素存在):param alignment: 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐:param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用:return: 返回获取到的元素文本内容"""page = self.get_current_url()element = self.find_element(locator=locator, mode=mode)if move_element is True:self.__move_element_visible(locator=locator, element=element, alignment=alignment)try:logger.debug(f"文本获取操作:获取{page}页面下的属性为:{locator}的元素的文本内容")return element.textexcept Exception as e:logger.error(f"页面{page}的元素:{locator}获取文本操作失败")self.set_error_img()raise edef click_radios(self, locator: tuple, method: str, amount: int = None, mode: str = 'visible',alignment: bool = False, move_element: bool = False) -> WebElement:"""复选框内容点击:param locator: 传入元素定位表达式:param mode:  visible(元素可见), exist(元素存在):param amount: 传入复选项的数量 例子如果是3个选项就传入3:param method: 选择对应的内容选择方式 all 点击复选框的全部内容 random 随机点击复选框的中的某一个选项 assign点击指定的某个复选项:param alignment: 默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐:param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用:return: 全部点击时无返回,其他返回被点击的元素"""# 定位到复选框一定是一组元素page = self.get_current_url()elements: list[WebElement] = self.find_elements(locator=locator, mode=mode)try:logger.debug('点击方式为:{}'.format(method))if method == 'all':# 点击复选项中每一个元素for ele in elements:if move_element is True:self.__move_element_visible(locator=locator, element=ele, alignment=alignment)ele.click()# 随机点击复选项中的某一个内容elif method == 'random':# 导入随机数包import random# 生成指定范围之内的随机数作为需要点击的radionum = random.randint(0, amount - 1)element = elements[num]if move_element is True:self.__move_element_visible(locator=locator, element=element, alignment=alignment)element.click()# 返回被点击的元素return element# 点击复选框中指定位置的选项elif method == 'assign':# 因为从0开始计数,所以传入的 amount-1element = elements[amount - 1]if move_element is True:self.__move_element_visible(locator=locator, element=element, alignment=alignment)element.click()return elementelse:logger.error('点击方式输入错误,请检查')except Exception as e:logger.error(f"页面{page}的元素:{locator}复选框点击操作失败")self.set_error_img()raise e@staticmethoddef element_is_selected(element: WebElement):"""判断元素是否勾选:param element: 需要校验是否勾选的元素:return: 选中是Ture 没有选择是False"""return element.is_selected()def select_contents_menu(self, locator: tuple, text: str, mode: str = 'visible', alignment: bool = False,move_element: bool = False) -> None:"""选择下拉菜单中的内容:param locator: 传入元素定位表达式:param text: 出入下拉列表需要选择的内容:param mode: visible(元素可见), exist(元素存在):param alignment:  默认对齐方式是元素和当前页面的底部对齐,可以传 alignment=''表示和顶部对齐:param move_element: 这里是布尔值 传入True 表示需要让元素滚动到页面可见区域 False 表示不用"""page = self.get_current_url()element = self.find_element(locator=locator, mode=mode)# 定义一个存储菜单内容的空列表option = []if move_element is True:self.__move_element_visible(locator=locator, element=element, alignment=alignment)try:# 获取下拉列表的内容options = element.find_elements_by_tag_name("option")for value in options:option.append(value)if text in option:Select(element).select_by_visible_text(text)else:logger.error(f"选项:{text}不在下拉列表之中请检查")except Exception as e:self.set_error_img()logger.error(f"页面{page}的元素:{locator}下拉框操作失败请检查")raise edef dispose_alert(self, action: str) -> str:"""处理页面alert:param action: 参数为 accept 点击alert的确定 dismiss点击alert的取消:return: 返回alert的文本内容 可能有些用例需要用这个参数去校验"""# 等待alert出现再去操作WebDriverWait(self.driver, 5, 0.5).until(ec.alert_is_present())alert: Alert = self.driver.switch_to.alert# 尝试点击alerttry:if action == 'accept':alert.accept()elif action == 'dismiss':alert.dismiss()else:logger.error('alert 处理参数错误请检查')return alert.textexcept Exception as e:logger.error('alert处理异常')raise edef get_text(self, locator: tuple):"""获取元素的文本值:param locator: 元素定位:return:"""try:elem = self.driver.find_element(*locator)value = elem.textreturn valueexcept NoSuchElementException as e:print(f"get未找到元素{e}")raise edef element_dyeing(self, element) -> None:"""将被操作的元素染色:return: None"""self.driver.execute_script("arguments[0].setAttribute('style', 'background: yellow; border: 2px solid red;');",element)def set_error_img(self) -> None:"""截图:return: None"""__time_tag = ReturnTime.get_timestamp()__img_path = self.__img_dir + f"/{__time_tag}.png"try:# 进行截图self.driver.save_screenshot(filename=__img_path)logger.error(f"截图成功文件名称为:{__time_tag}.png")__file = open(__img_path, "rb").read()allure.attach(__file, "用例执行失败截图", allure.attachment_type.PNG)except Exception as e:logger.error(f"执行失败截图未能正确添加进入测试报告:{e}")raise edef set_case_img(self) -> None:"""用例执行完毕截图,并且将截图加入allure测试报告中:return: 无返回值"""with allure.step("关键步骤截图"):__img_name = ReturnTime.get_timestamp()__img_path = self.__img_dir + f"/{__img_name}.png"try:# 截图前等待1秒防止图片没有正常加载time.sleep(1)self.driver.save_screenshot(filename=__img_path)logger.debug(f"用例执行完成,截图成功,文件名称为{__img_name}.png")# 读取图片信息__file = open(file=__img_path, mode="rb").read()allure.attach(__file, "关键步骤截图", allure.attachment_type.PNG)except Exception as e:logger.error(f"测试结果截图,未能正确添加进入测试报告:{e}")raise e# ------------------------ START: JS事件 ------------------------ #def execute_js(self, js, *args):"""执行javascript脚本js: 元组形式参数"""self.driver.execute_script(js, *args)return selfdef upload_file_pywinauto(self, file_path):"""使用pywinauto来上传缺点:只能在windows上使用。优点:可以选择多个文件,路径中有中文也可以。安装:pip install pywinauto -i https://mirrors.aliyun.com/pypi/simple/:param file_path: 文件绝对路径,支持传数组"""if isinstance(file_path, list):for path in file_path:# 上传文件send_keys(path)else:# 上传文件send_keys(file_path)# 点击回车send_keys("{VK_RETURN}")return selfdef upload_file_pyautogui(self, file_path):"""使用pyautogui来上传缺点:只能选择一个文件,路径中有中文会出问题。优点:跨平台。Linux, mac,windows都可以。安装:pip install pyautogui -i https://mirrors.aliyun.com/pypi/simple/:param file_path: 文件绝对路径,支持传数组"""if isinstance(file_path, list):print("只能选择一个文件,默认选择第一个")file_path = file_path[0]# 上传文件pyautogui.write(file_path)# 点击回车pyautogui.press("enter", 2)return self# ------------------------ END: JS事件 ------------------------ ## ------------------------ START: 鼠标事件:双击,悬停,拖动 ------------------------ #def double_click(self, locator):"""鼠标双击:param locator::return:"""try:elem = self.driver.find_element(*locator)action = ActionChains(self.driver)action.double_click(elem).perform()return selfexcept NoSuchElementException as e:print("未找到元素:{}".format(e))raise edef drag_and_drop(self, start_locator, end_locator):"""鼠标拖动"""elem_start = self.driver.find_element(*start_locator)elem_end = self.driver.find_element(*end_locator)action = ActionChains(self.driver)action.double_click((elem_start, elem_end)).perform()return selfdef hover(self, locator):"""鼠标悬停"""el = self.driver.find_element(*locator)action = ActionChains(self.driver)action.move_to_element(el).perform()return self

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

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

相关文章

【Leetcode】130.被围绕的区域

一、题目 1、题目描述 给你一个 m x n 的矩阵 board ,由若干字符 X 和 O ,找到所有被 X 围绕的区域,并将这些区域里所有的 O 用 X 填充。 示例1: 输入:board = [[“X”,“X”,“X”,“X”],[“X”,“O”,“O”,“X”],[“X”,“X”,“O”,“X”],[“X”,“O”,“X”,“…

高德地图jsapi报错INVALID_USER_SCODE

看了各种网上方法,还是搞不定。无奈在高德开放平台提了工单。 很快高德的技术人员就给出了答复“您好,您检查一下您的安全密钥是否在key之前,安全密钥设置必须是在JS API 脚本加载之前进行设置,否则设置无效。” 并给出了推荐的…

【数据结构】C语言队列(详解)

前言: 💥🎈个人主页:​​​​​​Dream_Chaser~ 🎈💥 ✨✨专栏:http://t.csdn.cn/oXkBa ⛳⛳本篇内容:c语言数据结构--C语言实现队列 目录 一.队列概念及结构 1.1队列的概念 1.2队列的结构 二.队列的实现 2.1头文…

【linux命令讲解大全】035.文件删除命令:rm 和 rmdir 的用法详解

文章目录 rm补充说明语法选项参数实例 rmdir补充说明语法选项参数实例 从零学 python rm 用于删除给定的文件和目录 补充说明 rm命令可以删除一个目录中的一个或多个文件或目录,也可以将某个目录及其下属的所有文件及其子目录均删除掉。对于链接文件,…

【python爬虫】6.爬虫实操(带参数请求数据)

文章目录 前言项目:狂热粉丝分析过程什么是带参数请求数据如何带参数请求数据 代码实现被隐藏的歌曲清单什么是Request Headers如何添加Request Headers 复习 前言 先来复习一下上一关的主要知识吧,先热个身。 Network能够记录浏览器的所有请求。我们最…

React Navigation 使用导航

在 Web 浏览器中,您可以使用锚标记链接到不同的页面。当用户单击链接时,URL 会被推送到浏览器历史记录堆栈中。当用户按下后退按钮时,浏览器会从历史堆栈顶部弹出该项目,因此活动页面现在是以前访问过的页面。React Native 不像 W…

AZ900备考

文章目录 云服务的概念云服务模型云服务类型消费的模型云服务的好处可靠性和可预测性的优势云中的管理 Azure 体系结构和服务核心结构组件物理基础结构组件 Azure计算和网络服务Azure 存储服务身份认证AD身份认证 Azure 管理和治理成本管理治理合规性的功能和工具管理和部署Azu…

代码随想录算法训练营第17期第34天 | 1005. K 次取反后最大化的数组和、134. 加油站、135. 分发糖果

1005. K 次取反后最大化的数组和 这里说一下卡哥和我的区别,基本思路是一样的, 只是卡哥这里只需要一次排序,而我这边排了两次; 卡哥思路: 1.按照绝对值大小从大到小排序 2.从前往后遍历,遇到负数将其转…

喷泉码浅谈

01、喷泉码简介 喷泉码(Fountain Code)是一种在无线通信、数据传输和网络编码领域中使用的错误纠正技术。它与传统的纠错码和编码方法有所不同,喷泉码被设计用于在不确定信道条件下的高效数据传输。传统的纠错码(如海明码、RS码等…

MAC苹果电脑如何压缩rar文件?

作为开发者,想必主力开发机肯定都以苹果的MacBook为主,究其原因,为非是因为其对开发者的友好性,且可同时进行iOS 以及android的app开发,但是windows在这方面就欠缺太多了,虽然很多人说可以使用,…

Linux服务器部署JavaWeb后端项目

适用于:MVVM前后台分离开发、部署、域名配置 前端:Vue 后端:Spring Boot 这篇文章只讲后端部署,前端部署戳这里 目录 Step1:服务器上搭建后端所需环境1、更新服务器软件包2、安装JDK83、安装MySQL4、登录MySQL5、修…

可视化绘图技巧100篇基础篇(九)-子弹图(一)

目录 前言 适用场景 图例 绘图工具及代码实现 Excel绘制子弹图 Python绘制子弹图

钉钉消息已读、未读咋实现的嘞?

前言 一款app,消息页面有:钱包通知、最近访客等各种通知类别,每个类别可能有新的通知消息,实现已读、未读功能,包括多少个未读,这个是怎么实现的呢?比如用户A访问了用户B的主页,难道…

Kotlin的内置函数 apply、let、run、with、also

let 1.let函数返回类型,是根据匿名函数的最后一行变化而变化 2.let函数中的匿名函数里面持有的是it 集合自身 fun main() {var num1 1var num2 1var result:Intresult num1 num2var str result?.let {//传入本身,it指代本身即result,result不为空…

Mac下Docker Desktop安装命令行工具、开启本地远程访问

Mac系统下,为了方便在terminal和idea里使用docker,需要安装docker命令行工具,和开启Docker Desktop本地远程访问。 具体方法是在设置-高级下, 1.将勾选的User调整为System,这样不用手动配置PATH即可使用docker命令 …

Nuxt 菜鸟入门学习笔记五:CSS 样式

文章目录 本地样式表在组件内导入通过 Nuxt 配置 CSS 属性导入使用字体导入通过 NPM 发布的样式表 外部样式表动态添加样式表【高级】使用 Nitro 插件修改渲染的头部 使用预处理器单文件组件 SFC 样式类和样式绑定使用 v-bind 的动态样式Scoped StylesCSS Modules预处理器支持 …

基于Python+OpenCV智能答题卡识别系统——深度学习和图像识别算法应用(含Python全部工程源码)+训练与测试数据集

目录 前言总体设计系统整体结构图系统流程图 运行环境Python 环境PyCharm安装OpenCV环境 模块实现1. 信息识别2. Excel导出模块3. 图形用户界面模块4. 手写识别模块 系统测试1. 系统识别准确率2. 系统识别应用 工程源代码下载其它资料下载 前言 本项目基于Python和OpenCV图像处…

多重背包模板题,P1776 宝物筛选

题目描述 终于,破解了千年的难题。小 FF 找到了王室的宝物室,里面堆满了无数价值连城的宝物。 这下小 FF 可发财了,嘎嘎。但是这里的宝物实在是太多了,小 FF 的采集车似乎装不下那么多宝物。看来小 FF 只能含泪舍弃其中的一部分…

【SA8295P 源码分析】87 - SA8295P HQNX + Android 编译环境搭建指导

【SA8295P 源码分析】87 - SA8295P HQNX + Android 编译环境搭建指导 一、Android 编译环境搭建:Android + sa8295p-hqx-4-2-4-0_hlos_dev_la.tar.gz1.1 更新 Ubuntu 18.04 源路径1.2 安装基础编译环境1.3 设置JDK8 的环境变量1.4 配置sh为bash(默认为dash)1.5 Android 编译…

图像扭曲之旋转

源码: void twirl(cv::Mat& src,cv::Mat& dst,double angle,double radius) {dst.create(src.rows, src.cols, CV_8UC3);dst.setTo(0);int radius2radius*radius;int cx src.cols / 2;int cy src.rows / 2;int distance,distance2 0;for (int h 0; h &…