總結Selenium WebDriver中一些鼠標和鍵盤事件的使用

在使用 Selenium WebDriver 做自動化測試的時候,會經常模擬鼠標和鍵盤的一些行為。比如使用鼠標單擊、雙擊、右擊、拖拽等動作;或者鍵盤輸入、快捷鍵使用、組合鍵使用等模擬鍵盤的操作。在 WebDeriver 中,有一個專門的類來負責實現這些測試場景,那就是 Actions 類,在使用該類的過程中會配合使用到 Keys 枚舉以及 Mouse、 Keyboard、CompositeAction 等類。

其次,在實際測試過程中,可能會遇到某些按鍵沒辦法使用 Actions、Keys 等類來實現的情況。 比如通過使用 Alt+PrtSc 組合鍵來實現截取屏幕當前活動窗口的圖像,在 Keys 枚舉中,因為沒有枚舉出 PrtSc 鍵,所以沒辦法通過 Action 的 KeyDown(Keys) 來模擬按下這個動作。

再次是在自動化測試中,可能會遇到一些附件、文件上傳的場景,或者是多文件上傳,這些在 Selenium2.0 之后,可以直接使用 WebElement 類的 sendKeys() 方法來實現。

下面就分別介紹這些情況的具體使用。

鼠標點擊操作

鼠標點擊事件有以下幾種類型:

清單 1. 鼠標左鍵點擊

Actions action = new Actions(driver);action.click();// 鼠標左鍵在當前停留的位置做單擊操作 
action.click(driver.findElement(By.name(element)))// 鼠標左鍵點擊指定的元素

清單 2. 鼠標右鍵點擊

Actions action = new Actions(driver); 
action.contextClick();// 鼠標右鍵在當前停留的位置做單擊操作 
action.contextClick(driver.findElement(By.name(element)))// 鼠標右鍵點擊指定的元素

清單 3. 鼠標雙擊操作

Actions action = new Actions(driver); 
action.doubleClick();// 鼠標在當前停留的位置做雙擊操作 
action.doubleClick(driver.findElement(By.name(element)))// 鼠標雙擊指定的元素

清單 4. 鼠標拖拽動作

Actions action = new Actions(driver); 
// 鼠標拖拽動作,將 source 元素拖放到 target 元素的位置。
action.dragAndDrop(source,target);
// 鼠標拖拽動作,將 source 元素拖放到 (xOffset, yOffset) 位置,其中 xOffset 為橫坐標,yOffset 為縱坐標。
action.dragAndDrop(source,xOffset,yOffset);

在這個拖拽的過程中,已經使用到了鼠標的組合動作,首先是鼠標點擊并按住 (click-and-hold) source 元素,然后執行鼠標移動動作 (mouse move),移動到 target 元素位置或者是 (xOffset, yOffset) 位置,再執行鼠標的釋放動作 (mouse release)。所以上面的方法也可以拆分成以下的幾個執行動作來完成:

action.clickAndHold(source).moveToElement(target).perform(); 
action.release();

清單 5. 鼠標懸停操作

Actions action = new Actions(driver); 
action.clickAndHold();// 鼠標懸停在當前位置,既點擊并且不釋放
action.clickAndHold(onElement);// 鼠標懸停在 onElement 元素的位置

action.clickAndHold(onElement) 這個方法實際上是執行了兩個動作,首先是鼠標移動到元素 onElement,然后再 clickAndHold, 所以這個方法也可以寫成 action.moveToElement(onElement).clickAndHold()。

清單 6. 鼠標移動操作

Actions action = new Actions(driver); 
action.moveToElement(toElement);// 將鼠標移到 toElement 元素中點
// 將鼠標移到元素 toElement 的 (xOffset, yOffset) 位置,
//這里的 (xOffset, yOffset) 是以元素 toElement 的左上角為 (0,0) 開始的 (x, y) 坐標軸。
action.moveToElement(toElement,xOffset,yOffset)
// 以鼠標當前位置或者 (0,0) 為中心開始移動到 (xOffset, yOffset) 坐標軸
action.moveByOffset(xOffset,yOffset);

action.moveByOffset(xOffset,yOffset) 這里需要注意,如果 xOffset 為負數,表示橫坐標向左移動,yOffset 為負數表示縱坐標向上移動。而且如果這兩個值大于當前屏幕的大小,鼠標只能移到屏幕最邊界的位置同時拋出 MoveTargetOutOfBoundsExecption 的異常。

鼠標移動操作在測試環境中比較常用到的場景是需要獲取某元素的 flyover/tips,實際應用中很多 flyover 只有當鼠標移動到這個元素之后才出現,所以這個時候通過執行 moveToElement(toElement) 操作,就能達到預期的效果。但是根據我個人的經驗,這個方法對于某些特定產品的圖標,圖像之類的 flyover/tips 也不起作用,雖然在手動操作的時候移動鼠標到這些圖標上面可以出現 flyover, 但是當使用 WebDriver 來模擬這一移動操作時,雖然方法成功執行了,但是 flyover 卻出不來。所以在實際應用中,還需要對具體的產品頁面做相應的處理。

清單 7. 鼠標釋放操

Actions action = new Actions(driver); 
action.release();// 釋放鼠標

鍵盤模擬操作

對于鍵盤的模擬操作,Actions 類中有提供 keyUp(theKey)、keyDown(theKey)、sendKeys(keysToSend) 等方法來實現。鍵盤的操作有普通鍵盤和修飾鍵盤(Modifier Keys, 下面的章節將講到修飾鍵的概念)兩種 :

1. 對于普通鍵盤,使用 sendKeys(keysToSend) 就可以實現,比如按鍵 TAB、Backspace 等。

清單 8. 普通鍵盤模擬 sendKeys(keysToSend)

Actions action = new Actions(driver); 
action.sendKeys(Keys.TAB);// 模擬按下并釋放 TAB 鍵
action.sendKeys(Keys.SPACE);// 模擬按下并釋放空格鍵
/***
針對某個元素發出某個鍵盤的按鍵操作,或者是輸入操作,
比如在 input 框中輸入某個字符也可以使用這個方法。這個方法也可以拆分成:
action.click(element).sendKeys(keysToSend)。
*/
action.sendKeys(element,keysToSend);

注意除了 Actions 類有 sendKeys(keysToSend)方法外,WebElement 類也有一個 sendKeys(keysToSend)方法,這兩個方法對于一般的輸入操作基本上相同,不同點在于以下幾點:

  • Actions 中的 sendKeys(keysToSend) 對于修飾鍵 (Modifier Keys) 的調用并不會釋放,也就是說當調用 actions.sendKeys(Keys.ALT); actions.sendKeys(Keys.CONTROL); action.sendKeys(Keys.SHIFT); 的時候,相當于調用 actions.keyDown(keysToSend),而如果在現實的應用中想要模擬按下并且釋放這些修飾鍵,應該再調用 action.sendKeys(keys.NULL) 來完成這個動作。
  • 其次就是當 Actions 的 sendKeys(keysToSend) 執行完之后,焦點就不在當前元素了。所以我們可以使用 sendKeys(Keys.TAB) 來切換元素的焦點,從而達到選擇元素的作用,這個最常用到的場景就是在用戶名和密碼的輸入過程中。
  • 第三點,在 WebDriver 中,我們可以使用 WebElement 類的 sendKeys(keysToSend) 來上傳附件,比如 element.sendKeys(“C:\\test\\uploadfile\\test.jpg”); 這個操作將 test.jpg 上傳到服務器,但是使用:
Actions action = New Actions(driver); action.sendKeys(element,“C:\\test\\upload\\test.jpg”); 
action.click(element).sendKeys(“C:\\test\\upload\\test.jpg”);

這種方式是上傳不成功的,雖然 WebDriver 在執行這條語句的時候不會出錯,但是實際上并沒有將文件上傳。所以要上傳文件,還是應該使用前面一種方式。

2.對于修飾鍵(Modifier keys),一般都是跟普通鍵組合使用的。比如 Ctrl+a、Alt+F4、 Shift+Ctrl+F 等等。

  • 這里先解釋一下修飾鍵的概念,修飾鍵是鍵盤上的一個或者一組特別的鍵,當它與一般按鍵同時使用的時候,用來臨時改變一般鍵盤的普通行為。對于單獨按下修飾鍵本身一般不會觸發任何鍵盤事件。在個人計算機上的鍵盤上,有以下幾個修飾鍵:Shift、Ctrl、Alt(Option)、AltGr、Windows logo、Command、FN(Function)。但是在 WebDriver 中,一般的修飾鍵指前面三個。你可以點擊下面的 Wiki 鏈接去了解更多有關修飾鍵的信息,Modifier key。
  • 回到上面的話題,在 WebDriver 中對于修飾鍵的使用需要用到 KeyDown(theKey)、keyUp(theKey) 方法來操作。

清單 9. 修飾鍵方法 KeyDown(theKey)、keyUp(theKey)

 Actions action = new Actions(driver); action.keyDown(Keys.CONTROL);// 按下 Ctrl 鍵action.keyDown(Keys.SHIFT);// 按下 Shift 鍵action.keyDown(Key.ALT);// 按下 Alt 鍵action.keyUp(Keys.CONTROL);// 釋放 Ctrl 鍵action.keyUp(Keys.SHIFT);// 釋放 Shift 鍵action.keyUp(Keys.ALT);// 釋放 Alt 鍵

所以要通過 Alt+F4 來關閉當前的活動窗口,可以通過下面語句來實現:

action.keyDown(Keys.ALT).keyDown(Keys.F4).keyUp(Keys.ALT).perform();

而如果是對于像鍵盤上面的字母鍵 a,b,c,d... 等的組合使用,可以通過以下語句實現 :

action.keyDown(Keys.CONTROL).sednKeys(“a”).perform();

在 WebDriver API 中,KeyDown(Keys theKey)、KeyUp(Keys theKey) 方法的參數只能是修飾鍵:Keys.SHIFT、Keys.ALT、Keys.CONTROL, 否者將拋出 IllegalArgumentException 異常。 其次對于 action.keyDown(theKey) 方法的調用,如果沒有顯示的調用 action.keyUp(theKey) 或者 action.sendKeys(Keys.NULL) 來釋放的話,這個按鍵將一直保持按住狀態。

使用 Robot 類來操作 Keys 沒有枚舉出來的按鍵操作

1.在 WebDriver 中,Keys 枚舉出了鍵盤上大多數的非字母類按鍵,從 F1 到 F10,NUMPAD0 到 NUMPAD9、ALT\TAB\CTRL\SHIFT 等等,你可以通過以下鏈接查看 Keys 枚舉出來的所有按鍵,Enum Keys。 但是并沒有列出鍵盤上的所有按鍵,比如字母鍵 a、b、c、d … z,一些符號鍵比如:‘ {}\[] ’、‘ \ ’、‘。’、‘ ? ’、‘:’、‘ + ’、‘ - ’、‘ = ’、、‘“”’,還有一些不常用到的功能鍵如 PrtSc、ScrLk/NmLk。對于字母鍵和符號鍵,前面我們已經提到可以直接使用 sendKeys(“a”),sendKeys(“/”) 的方式來觸發這些鍵盤事件。而對于一些功能組合鍵,如 Fn + NmLk 來關閉或者打開數字鍵,或者 Alt+PrtSC 來抓取當前屏幕的活動窗口并保存到圖片,通過 WebDriver 的 Keys 是沒辦法操作的。 這個時候我們就需要用到 Java 的 Robot 類來實現對這類組合鍵的操作了。

2.下面就以對 Alt+PrtSc 為例介紹一下 Robot 對鍵盤的操作。如代碼清單 10。

清單 10. 通過 Robot 發出組合鍵動作

/** * * @Description: 這個方法用來模擬發送組合鍵 Alt + PrtSc, 當組合鍵盤事件執行之后,屏幕上的活動窗口* 就被截取并且存儲在剪切板了。 接下來就是通過讀取剪切板數據轉換成 Image 圖像對象并保存到本地。* @param filename : 要保存的圖像的名稱*/ public static void sendComposeKeys(String fileName) throws Exception { // 構建 Robot 對象,用來操作鍵盤Robot robot = new Robot(); // 模擬按下鍵盤動作,這里通過使用 KeyEvent 類來獲取對應鍵盤(ALT)的虛擬鍵碼robot.keyPress(java.awt.event.KeyEvent.VK_ALT); // 按下 PrtSC 鍵robot.keyPress(java.awt.event.KeyEvent.VK_PRINTSCREEN); // 釋放鍵盤動作,當這個動作完成之后,模擬組合鍵 Alt + PrtSC 的過程就已經完成,
//此時屏幕活動窗口就一被截取并存入到剪切板robot.keyRelease(java.awt.event.KeyEvent.VK_ALT); // 獲取系統剪切板實例Clipboard sysc = Toolkit.getDefaultToolkit().getSystemClipboard(); // 通過 getContents() 方法就可以將剪切板內容獲取并存入 Transferable 對象中Transferable data = sysc.getContents(null); if (data != null) { 
/***
判斷從剪切板獲取的對象內容是否為 Java Image 類, 如果是將直接轉化為 Image 對象。
到此為止,我們就從發出組合鍵到抓取活動窗口,再讀取剪切板并存入 Image 對象的過程
就完成了,接下來要做的就是需要將 Image 對象保存到本地。
*/if (data.isDataFlavorSupported(DataFlavor.imageFlavor)) { Image image = (Image) data .getTransferData(DataFlavor.imageFlavor); writeImageToFile(image, fileName); } } }

Robot 類對鍵盤的處理是通過 keyPress(int keycode)、keyRelease(int keycode) 方法來實現的,其中他們需要的參數是鍵盤按鍵對應的虛擬鍵碼,虛擬鍵碼的值可以通過 KeyEvent 類來獲取。在 Java API 中對于虛擬鍵碼的解釋如下: 虛擬鍵碼用于報告按下了鍵盤上的哪個鍵,而不是一次或多次鍵擊組合生成的字符(如 "A" 是由 shift + "a" 生成的)。 例如,按下 Shift 鍵會生成 keyCode 為 VK_SHIFT 的 KEY_PRESSED 事件,而按下 'a' 鍵將生成 keyCode 為 VK_A 的 KEY_PRESSED 事件。釋放 'a' 鍵后,會激發 keyCode 為 VK_A 的 KEY_RELEASED 事件。另外,還會生成一個 keyChar 值為 'A' 的 KEY_TYPED 事件。 按下和釋放鍵盤上的鍵會導致(依次)生成以下鍵事件:

KEY_PRESSED

KEY_TYPED(只在可生成有效 Unicode 字符時產生。)

KEY_RELEASED

所以當測試中需要用到按下鍵盤 Alt+PrtSc 鍵的時候,只需要執行代碼清單 10 中兩個 keyPress() 和一個 keyRelease() 方法即可。

3.當這兩個按鍵執行結束之后,屏幕上面的活動窗口已經保存到剪切板中。如果需要將其保存本地圖片,只需要從剪切板讀取并通過 JPEGImageEncoder 類或者 ImageIO 類將其寫入本地即可。

清單 11. 使用 JPEGImageEncoder 將 Image 對象保存到本地

/** * * @Description: 這個方法用來將 Image 對象保存到本地,主要是通過 JPEGImageEncoder 類來實現圖像的* 保存* @param image : 要保存的 Image 對象* @param filename : 保存圖片的文件名稱*/ public static void writeImageToFile(Image image, String fileName) { try { // 獲取 Image 對象的寬度和高度, 這里的參數為 null 表示不需要通知任何觀察者int width = image.getWidth(null);int height = image.getHeight(null); BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 通過 BufferedImage 繪制圖像并保存在其對象中bi.getGraphics().drawImage(image, 0, 0, null); // 構建圖像名稱及保存路徑String name = Const.DIRECTORY + fileName + Const.FORMAT; File dir = new File(Const.DIRECTORY); if (!dir.exists()) { dir.mkdir(); } FileOutputStream out = new FileOutputStream(name); @SuppressWarnings("restriction") JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); encoder.encode(bi); out.flush(); out.close(); } catch (Exception e) { e.printStackTrace(); } }

代碼清單 11 是通過 JPEGImageEncoder 類將 Image 對象寫到本地文件流,注意 Image 對象是在代碼清單 10 中的如下語句獲取到的:

Clipboard sysc = Toolkit.getDefaultToolkit().getSystemClipboard(); Transferable data = sysc.getContents(null); if (data != null) { if (data.isDataFlavorSupported(DataFlavor.imageFlavor)) { Image image = (Image) data .getTransferData(DataFlavor.imageFlavor); writeImageToFile(image, fileName); } }

清單 12. 使用 ImageIO 將 Image 對象保存到本地

/** * * @Description: 通過使用 ImageIO 類來保存 Image 對象為本地圖片* @param image : 需要保存的 Image 對象* @param filename : 文件名*/ public static void saveImage(Image image, String fileName) throws Exception { // 獲取 Image 對象的高度和寬度int width = image.getWidth(null); int height = image.getHeight(null); BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g = bi.getGraphics(); //通過 BufferedImage 繪制圖像并保存在其對象中g.drawImage(image, 0, 0, width, height, null); g.dispose(); File f = new File(fileName); // 通過 ImageIO 將圖像寫入到文件ImageIO.write(bi, "jpg", f); }

使用 sendKeys(keysToSend) 批量上傳文件

在 Selenium2.0 之前,要上傳文件是比較麻煩的一件事件,因為點擊 Upload File 控件會彈出 Windows 窗口以提供用戶選擇文件,但是 Window 窗口已經是瀏覽器之外的組件,所以 Selenium 本身沒辦法控制, 而必須使用 Java Robot 類來模擬鍵盤去操作剪切板實現上傳功能,而且及其不穩定。 在 Selenium 2.0 之后,WebDriver 解決了這個問題。前面已經談到過,直接使用 WebElement 類的 sendKeys(keysToSend) 方法就可以實現文件上傳了。但是如果想批量上傳文件,使用 element.sendKeys(“C:\\test\\upload\\test1.txt”, “C:\\test\\upload\\test2.txt”...) 方法也是不行的,它能通過執行,但是實際上沒有上傳成功。這時可以通過循環的方式來實現文件的批量上傳,代碼清單 13 是我在百度云上面批量上傳文件的測試。

清單 13. 批量上傳文件

/** * * @Description: 在百度云上測試文件批量上傳功能,主要是通過循環的方式去做單一* 的上傳動作 , 登陸過程已經去掉*/ @Test public void test_mutilUploadFile() throws Exception { System.out.println("upload start"); // 獲取上傳控件元素WebElement uploadButton = driver.findElement(By.name("html5uploader")); // 構建上傳文件路徑,將需要上傳的文件添加到 CharSequence 數組CharSequence[] files = new CharSequence[5]; files[0] = "C:\\test\\test1.txt"; files[1] = "C:\\test\\test2.txt"; files[2] = "C:\\test\\test3.txt"; files[3] = "C:\\test\\test4.txt"; files[4] = "C:\\test\\test5.txt"; // 循環列出每支需要上傳的文件路徑,做單一上傳動作for(CharSequence file: files){ uploadButton.sendKeys(file); } Thread.sleep(2000); System.out.println("upload end"); }

模擬雙擊操作

1. 模擬雙擊一個div,驗證點擊之前的字體為14號
2. 點擊后字體為20號
Actions builder = new Actions(driver); //new 出Actions對象
builder.doubleClick(message).build().perform(); //對象后可以跟一系列的操作,要通過跟著build().perform()才能執行
package com.example.tests;
import static org.junit.Assert.*;
import org.junit.*;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;
public class Selenium2 {
WebDriver driver = new FirefoxDriver();
@Test
public void tableTest() {
driver.get("D:\\demo\\DoubleClickDemo.html");
WebElement message = driver.findElement(By.id("message"));
//  驗證初始字體為14px
assertEquals("14px", message.getCssValue("font-size"));
Actions builder = new Actions(driver);
builder.doubleClick(message).build().perform();
//  驗證點擊后字體變為20px
assertEquals("20px", message.getCssValue("font-size"));
driver.close();
}
}
模擬拖拽操作
使用dragAndDrop(source,targe)方法
package com.example.tests;
import static org.junit.Assert.*;
import org.junit.*;
import org.openqa.selenium.*;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.interactions.Actions;
public class Selenium2 {
@Test
public void testDragDrop() {
WebDriver driver = new InternetExplorerDriver();
driver.get("D:\\demo\\DragAndDrop.html");
WebElement source = driver.findElement(By.id("draggable"));
WebElement target = driver.findElement(By.id("droppable"));
Actions builder = new Actions(driver);
builder.dragAndDrop(source, target).perform();
try {
assertEquals("Dropped!", target.getText());
} catch (Error e) {
e.printStackTrace();
}finally{
driver.close();
}
}
}

結束語

在 Selenium WebDriver 中,有了 Actions 類和 Keys 枚舉對鍵盤和鼠標的操作已經做的非常到位,再結合 Java 本身 Robot、KeyEvent 等類的使用,基本上可以滿足工作中遇到的對鼠標鍵盤操作的應用了。

其次要注意的地方是 WebDriver 對瀏覽器的支持問題,Selenium WebDriver 支持的瀏覽器非常廣泛,從 IE、Firefox、Chrome 到 Safari 等瀏覽器, WebDriver 都有相對應的實現:InterntExplorerDriver、FirefoxDriver、ChromeDriver、SafariDriver、AndroidDriver、 IPhoneDriver、HtmlUnitDriver 等。根據個人的經驗,Firefox 以及 Chrome 瀏覽器對 WebDriver 的支持最好了,Firefox 搭上 Firebug 以及 Firepath, 在寫腳本的過程中非常方便,而 ChromeDriver 是 Google 公司自己支持與維護的項目。HtmlUnitDriver 速度最快,一個純 Java 實現的瀏覽器。IE 比較慢,而且對于 Xpath 等支持不是很好。更多關于 Selenium WebDriver 的知識,大家可以從下面的鏈接去訪問 Selenium 官方文檔。

轉載于:https://www.cnblogs.com/MasterMonkInTemple/p/10365168.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/449961.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/449961.shtml
英文地址,請注明出處:http://en.pswp.cn/news/449961.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

最快浮點數取絕對值

做視頻算法10多年&#xff0c;經常要算絕對值&#xff0c;整數的絕對值有快速算法&#xff0c;但浮點數的絕對值沒看到有快速算法&#xff0c;經常不段發現&#xff0c;得到如下浮點數的快速算法&#xff1a; 快6倍多&#xff0c; #include <Windows.h> #include <ios…

Linux ln命令、軟鏈接和硬鏈接的區別

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Linux ln命令是一個非常重要命令&#xff0c;它的功能是為某一個文件在另外一個位置建立一個同步的鏈接。 當我們需要在不同的目錄&…

Android應用開發——文件目錄

Android 存儲位置及 API 一、內部存儲 應用安裝后都會在Android 根目錄生成 /data/data/packagename&#xff0c;當前應用讀取不需要讀寫權限 注意&#xff1a; 有些開發者可能看到過應用的根目錄為 /data/user/0/packagename 的情況&#xff0c;這里解釋一下&#xff0c;And…

git常用命令及沖突解決

2019獨角獸企業重金招聘Python工程師標準>>> git常用命令 git config --global user.name chenhongjiang git config --global user.email 123qq.com git init 建立廠庫 git status 查看狀態 git add . 添加當前目錄 git add a.php 添加文件…

C 語言常見問題集

從 http://c-faq-chn.sourceforge.net/ccfaq/index.html 轉載過來&#xff0c;學習C的好助手。 目錄1. 前言2. 聲明和初始化 2.1 我如何決定使用那種整數類型&#xff1f;2.2 64 位機上的 64 位類型是什么樣的&#xff1f;2.3 怎樣定義和聲明全局變量和函數最好&#xff1f;2.4…

【題解】quake

【題解】\(quake\) 題目大意 我們共有報酬\(f\)元&#xff0c;一條邊有它的價值\(w_i\),有它的建造時間\(t_i\)。要求建一些邊&#xff0c;生成一顆樹。求最大的利潤率。 數據范圍 \(n\le 400\) \(m\le10000\) \(Solution\) 實際上\(n,m\)出到\(\le 100000\)應該也是沒問題的。…

Android應用開發——service連接泄露異常:android.app.ServiceConnectionLeaked: that was originally bound here

在做service開發過程中&#xff0c;大部分可能會遇到以下異常&#xff0c;該異常僅通過log輸出&#xff0c;并不會導致app crash。 E/ActivityThread: Activity com.example.image.all_samples.Main2Activity has leaked ServiceConnection com.example.image.all_samples.Mai…

Linux more命令、Linux rhmask命令

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Linux more 命令類似 cat &#xff0c;不過會以一頁一頁的形式顯示&#xff0c;更方便使用者逐頁閱讀&#xff0c;而最基本的指令就是按…

從零開始學習PYTHON3講義(二)把Python當做計算器

《從零開始PYTHON3》第二講 上一講我們說過了如何啟動Python IDLE集成開發學習環境&#xff0c;macOS/Linux都可以在命令行執行idle3。Windows則從開始菜單中去尋找IDLE程序的圖標。 上一講我們還見到了Python的兩種工作模式&#xff0c;交互模式和程序模式。 通常在一個大型的…

Tranquility

本頁目錄與Kafka集群交互Druid使用Tranquility Kafka本文以Kafka為例&#xff0c;介紹在E-MapReduce中如何使用Tranquility從Kafka集群采集數據&#xff0c;并實時推送至Druid集群。 Tranquility是一個以push方式向Druid實時發送數據的應用。它替用戶解決了分區、多副本、服務發…

Iot相關雜燴

人工智能就像人的大腦&#xff0c;而 IoT 就像人的神經網絡 1&#xff09;在天空中巨大的鳥群里&#xff0c;每一只鳥兒都實時判斷自己和四周同伴的距離。這時&#xff0c;它們各自都是一個物聯網節點。2&#xff09;這些“節點”并不是簡單地收集數據&#xff0c;而是在實時計…

水滴石穿C語言之指針、數組和函數

基本解釋   1、指針的本質是一個與地址相關的復合類型&#xff0c;它的值是數據存放的位置&#xff08;地址&#xff09;&#xff1b;數組的本質則是一系列的變量。   2、數組名對應著&#xff08;而不是指向&#xff09;一塊內存&#xff0c;其地址與容量在生命期內保持…

告訴你銀行在年底為存儲做的小動作

25年前&#xff0c;銀行的存款利率是10.98%&#xff0c;可謂巔峰時刻。15年前&#xff0c;銀行的存款利率開始下降&#xff0c;降到了8%的利率。 到了5年前&#xff0c;銀行的存款利率毫無回轉之勢&#xff0c;直線下降到了5%的利率。 而如今&#xff0c;我們無可奈何地接受了2…

爬蟲學習(五)——百度貼吧的爬取

import osimport timeimport urllib.requestimport urllib.parse# 輸入目標頁碼和吧名def header(): url "https://tieba.baidu.com/f?" baming input("請輸入要爬取的吧名") start_page int(input("請輸入起始頁")) end_page …

什么是嵌入式設備?/ 嵌入式設備的定義

什么是嵌入式設備&#xff1f;/ 嵌入式設備的定義 區別于通用計算機的其他設備都可以稱之為嵌入式設備 &#xff08;個人電腦&#xff0c;服務器&#xff09; 一段時期內&#xff0c;必備的硬件配置。 嵌入式開發包括哪些部分&#xff1a; 底層驅動開發&#xff1a; 關鍵字…

Linux mv命令、Linux cp命令、Linux scp命令

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Linux mv命令用來為文件或目錄改名、或將文件或目錄移入其它位置。 語法 mv [options] source dest mv [options] source... director…

創業者談:畏懼失敗,但也要擁抱失敗

摘要&#xff1a;本文作者為Paydirt創始人Tristan Gamilis&#xff0c;他在文中分享了如何面對創業過程中的失敗。作為一個創業者&#xff0c;開始的時候并非全才&#xff0c;很多知識都是經歷了創業中的失敗&#xff0c;摸爬滾打之后才學會的。所以&#xff0c;我們在創業過程…

基于STM32F4移植W5500官方驅動庫ioLibrary_Driver(轉)

源&#xff1a; 基于STM32F4移植W5500官方驅動庫ioLibrary_Driver 參考&#xff1a; 基于STM32W5500 的Ethernet和Internet移植 Upgrade W5500 Throughput on Nucleo STM32F401RE Using SPI DMA

redis 資料

redis是什么: Redis is an open source, BSD licensed, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets. redis是開源,BSD許可,高級的key-value存儲系統. 可以用來存儲字…

Android應用開發——onStop的調用時機

onStop的調用時機&#xff0c;網上搜索到的說法大概是&#xff1a;“ onStop的調用是“The activity is no longer visible”&#xff0c;也就是完全不可見的時候調用的&#xff0c;這個完全不可見真的就是指視覺上的完全看不到而已&#xff0c;無論是按home鍵返回桌面&#xf…