想爬取外網steam的資料,但是steam官網在海外,加上steam處於反爬考慮,對於非同步資料-json資料進行處理,導致如果直接去拿人家的ajax介面作為請求url進行爬取就爬取得到一堆亂碼的沒用資料。---解決:使用Selenium 模擬使用者使用瀏覽器(通過js渲染),然後再解析處理selenium下載器下載下來的資料。
但是一開始,專案中selenium底層是使用phantomjs 作為驅動器(瀏覽器),出現瞭如下的一系列:
[ERROR - 2023-03-07T12:00:29.232Z] Session [258893b0-bcdf-11ed-9fc2-3f99c08d4ed8] - page.onError - msg: ReferenceError: Can't find variable: InitMiniprofileHovers
phantomjs://platform/console++.js:263 in error
[ERROR - 2023-03-07T12:00:29.233Z] Session [258893b0-bcdf-11ed-9fc2-3f99c08d4ed8] - page.onError - stack:
global code (https://store.steampowered.com/charts/topselling/SG:671)
phantomjs://platform/console++.js:263 in error
[ERROR - 2023-03-07T12:00:30.743Z] Session [258893b0-bcdf-11ed-9fc2-3f99c08d4ed8] - page.onError - msg: ReferenceError: Can't find variable: WebStorage
phantomjs://platform/console++.js:263 in error
[ERROR - 2023-03-07T12:00:30.744Z] Session [258893b0-bcdf-11ed-9fc2-3f99c08d4ed8] - page.onError - stack:
(anonymous function) (https://store.st.dl.eccdnx.com/public/shared/javascript/shared_responsive_adapter.js?v=TNYlyRmh1mUl&l=schinese&_cdn=china_eccdnx:43)
l (https://store.st.dl.eccdnx.com/public/shared/javascript/jquery-1.8.3.min.js?v=.TZ2NKhB-nliU&_cdn=china_eccdnx:2)
fireWith (https://store.st.dl.eccdnx.com/public/shared/javascript/jquery-1.8.3.min.js?v=.TZ2NKhB-nliU&_cdn=china_eccdnx:2)
ready (https://store.st.dl.eccdnx.com/public/shared/javascript/jquery-1.8.3.min.js?v=.TZ2NKhB-nliU&_cdn=china_eccdnx:2)
A (https://store.st.dl.eccdnx.com/public/shared/javascript/jquery-1.8.3.min.js?v=.TZ2NKhB-nliU&_cdn=china_eccdnx:2)
phantomjs://platform/console++.js:263 in error
[ERROR - 2023-03-07T12:00:30.746Z] Session [258893b0-bcdf-11ed-9fc2-3f99c08d4ed8] - page.onError - msg: ReferenceError: Can't find variable: GetNavCookie
Page page = downloader.download(request, this);//爬蟲任務的下載器,開始下載頁面
//獲取到web驅動器
webDriver = webDriverPool.get();
//驅動器下載頁面
webDriver.get(request.getUrl());//這裡出錯
▪ webDriver變數的情況:
this.execute("get", ImmutableMap.of("url", url));//執行下載命令
response = this.executor.execute(command);//響應體,即執行命令後的結果
//command 只是一個封裝了sessionId, driverCommand-get, 請求引數url的物件
Response var2 = super.execute(command);
...
報錯原因:是phantomis設計的不夠合理: 在頁面尋找不到dom元素的時候,合理設計應該返回nul,而不應該throw異常。
網友的錯誤原因--加密方式,理由:PhantomJS使用的加密方式是SSLv3,有些網站用的是TLS。
解決加密問題的方法:--ignore-ssl-errors=true 和 --ssl-protocol=any
▷ 自己的專案中的 web驅動器/瀏覽器(排除加密方式的原因):
phantomjs在對ES6的支援上天生有坑,前端使用ES6的網站都不建議用phantomis去跑。
發現微軟的瀏覽器Edge 開啟steam 官網,不開vpn,也很流暢,不過要是steam的連結帶上地理位置,例如香港,又打不開了,解決:vpn
發現,在專案呼叫完爬蟲框架的排程器後,下載器開始發揮作用。
case CHROME:
if (isWindows) {
System.setProperty("selenuim_config", "C:\\data\\config\\config-chrome.ini");
SeleniumDownloader seleniumDownloader = new SeleniumDownloader("C:\\data\\config\\chromedriver.exe");
// 瀏覽器開啟10s後才開始爬取資料
seleniumDownloader.setSleepTime(10 * 1000);
autoSpider.setDownloader(seleniumDownloader);
}
業務中,我們是通過了建立了SeleniumDownloader的下載器來下載頁面,但是確定就是底層的瀏覽器是純淨普通版的瀏覽器。
看到業務在建立SeleniumDownloader的下載器的時候,給它注入了一個組態檔config-chrome.ini,
但是發現這個組態檔是一個啟動檔案,裡面並沒options的屬性可以設定。
啟動檔案的設定,沒法實現
是否有暴露給外界什麼屬性可以設定options,閱讀原始碼後,發現它只暴露一個屬性就是設定啟動檔案config-chrome.ini。
public void configure() throws IOException {
// Read config file
sConfig = new Properties();
String configFile = DEFAULT_CONFIG_FILE;
if (System.getProperty("selenuim_config")!=null){
configFile = System.getProperty("selenuim_config");
}
sConfig.load(new FileReader(configFile));
// Prepare capabilities
sCaps = new DesiredCapabilities();
sCaps.setJavascriptEnabled(true);
sCaps.setCapability("takesScreenshot", false);
String driver = sConfig.getProperty("driver", DRIVER_PHANTOMJS);
// Fetch PhantomJS-specific configuration parameters
......
}
下載器和驅動器管理池都是在官網提供的原始碼的基礎進行修改;
SeleniumDownloader2:在SeleniumDownloader基礎上新增了代理列舉屬性proxyEnum,並使用了自己重寫的瀏覽器驅動池WebDriverPool2
WebDriverPool2:改寫了 WebDriverPool的構造器,以及改寫了初始化 WebDriver範例的configure方法(目的,就是為了增加上像代理等的options選項)
- 當然,還增加了一個輪詢方法incrForLoop,目的就是為了獲得代理列表的索引
用省略號表示代理和官網的是一摸一樣的!
細節: ChromeOptions需要設定ssl協定(官網給出的demo沒加,導致我開vpn一直沒成功,又沒提示.....)
分析和解決:因為https=http+ssl/tls,我們通過瀏覽器存取的時候,瀏覽器會把所有url地址都處理成安全通訊協定,所以程式碼中需要設定ssl協定
public class WebDriverPool2 {
......
/** 代理列舉引數 */
private final ProxyEnum proxyEnum;
/** 代理列表 */
private List<String> proxies;
/** ip代理列表的索引 */
private final AtomicInteger pointer = new AtomicInteger(-1);
......
/**
* 初始化一個 WebDriver 範例
* @throws IOException 異常
*/
public void configure() throws IOException {
......
if (isUrl(driver)) {
sCaps.setBrowserName("phantomjs");
mDriver = new RemoteWebDriver(new URL(driver), sCaps);
} else if (driver.equals(DRIVER_FIREFOX)) {
mDriver = new FirefoxDriver(sCaps);
} else if (driver.equals(DRIVER_CHROME)) {
if(proxyEnum == ProxyEnum.VPN_ENABLE || proxyEnum == ProxyEnum.PROXY_ENABLE){
//給谷歌瀏覽器,新增上ip代理或vpn等options
ChromeOptions options = new ChromeOptions();
//禁止載入圖片
options.addArguments("blink-settings=imagesEnabled=false");
Proxy proxy = new Proxy();
String httpProxy = proxies.get(incrForLoop());
// 需要設定ssl協定
proxy.setHttpProxy(httpProxy).setSslProxy(httpProxy);
options.setCapability("proxy",proxy);
sCaps.setCapability(ChromeOptions.CAPABILITY, options);
logger.info("chrome webDriver proxy is : " + proxy);
}
mDriver = new ChromeDriver(sCaps);
} else if (driver.equals(DRIVER_PHANTOMJS)) {
mDriver = new PhantomJSDriver(sCaps);
}
}
/**
* 輪詢:從代理列表選出一個代理的索引
* @return 索引
*/
private int incrForLoop() {
int p = pointer.incrementAndGet();
int size = proxies.size();
if (p < size) {
return p;
}
while (!pointer.compareAndSet(p, p % size)) {
p = pointer.get();
}
return p % size;
}
public WebDriverPool2(int capacity, ProxyEnum proxyEnum, MasterWebservice masterWebservice) {
this.capacity = capacity;
//設定代理的情況
this.proxyEnum = proxyEnum;
//vpn的情況
if(proxyEnum == ProxyEnum.VPN_ENABLE){
this.proxies = masterWebservice.getVpn();
//ip代理的情況
}else if(proxyEnum == ProxyEnum.PROXY_ENABLE){
//獲取動態生成的ip列表,帶有埠的,引數形式舉例 42.177.155.5:75114
this.proxies = masterWebservice.getProxyIps();
}
}
}
/**
* 在SeleniumDownloader基礎上新增了代理列舉屬性proxyEnum
* 並且要把官網SeleniumDownloader程式碼中使用WebDriverPool(實際是使用上咱改寫的WebDriverPool2)的方法引入,還有使用到WebDriverPool的方法
* 中,需要的屬性,要注意父類別中被設定私有,需要重寫一下(從父類別copy到子類就行啦)
*/
public class SeleniumDownloader2 extends SeleniumDownloader {
private volatile WebDriverPool2 webDriverPool;
/** 代理列舉引數 */
private ProxyEnum proxyEnum;
/** 通過masterWebservice獲得遠端的動態ip列表 */
private MasterWebservice masterWebservice;
public SeleniumDownloader2(String chromeDriverPath, ProxyEnum proxyEnum, MasterWebservice masterWebservice) {
System.getProperties().setProperty("webdriver.chrome.driver",
chromeDriverPath);
this.proxyEnum = proxyEnum;
this.masterWebservice = masterWebservice;
}
......
}
■ seleniume 包下的下載器和瀏覽器如下:
package us.codecraft.webmagic.downloader.selenium;
import org.apache.log4j.Logger;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriverService;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author [email protected] <br>
* Date: 13-7-26 <br>
* Time: 下午1:41 <br>
*/
class WebDriverPool {
private Logger logger = Logger.getLogger(getClass());
private final static int DEFAULT_CAPACITY = 5;
private final int capacity;
private final static int STAT_RUNNING = 1;
private final static int STAT_CLODED = 2;
private AtomicInteger stat = new AtomicInteger(STAT_RUNNING);
/*
* new fields for configuring phantomJS
*/
private WebDriver mDriver = null;
private boolean mAutoQuitDriver = true;
private static final String DEFAULT_CONFIG_FILE = "/data/webmagic/webmagic-selenium/config.ini";
private static final String DRIVER_FIREFOX = "firefox";
private static final String DRIVER_CHROME = "chrome";
private static final String DRIVER_PHANTOMJS = "phantomjs";
protected static Properties sConfig;
protected static DesiredCapabilities sCaps;
/**
* Configure the GhostDriver, and initialize a WebDriver instance. This part
* of code comes from GhostDriver.
* https://github.com/detro/ghostdriver/tree/master/test/java/src/test/java/ghostdriver
*
* @author [email protected]
* @throws IOException
*/
public void configure() throws IOException {
// Read config file
sConfig = new Properties();
String configFile = DEFAULT_CONFIG_FILE;
if (System.getProperty("selenuim_config")!=null){
configFile = System.getProperty("selenuim_config");
}
sConfig.load(new FileReader(configFile));
// Prepare capabilities
sCaps = new DesiredCapabilities();
sCaps.setJavascriptEnabled(true);
sCaps.setCapability("takesScreenshot", false);
String driver = sConfig.getProperty("driver", DRIVER_PHANTOMJS);
// Fetch PhantomJS-specific configuration parameters
if (driver.equals(DRIVER_PHANTOMJS)) {
// "phantomjs_exec_path"
if (sConfig.getProperty("phantomjs_exec_path") != null) {
sCaps.setCapability(
PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY,
sConfig.getProperty("phantomjs_exec_path"));
} else {
throw new IOException(
String.format(
"Property '%s' not set!",
PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY));
}
// "phantomjs_driver_path"
if (sConfig.getProperty("phantomjs_driver_path") != null) {
System.out.println("Test will use an external GhostDriver");
sCaps.setCapability(
PhantomJSDriverService.PHANTOMJS_GHOSTDRIVER_PATH_PROPERTY,
sConfig.getProperty("phantomjs_driver_path"));
} else {
System.out
.println("Test will use PhantomJS internal GhostDriver");
}
}
// Disable "web-security", enable all possible "ssl-protocols" and
// "ignore-ssl-errors" for PhantomJSDriver
// sCaps.setCapability(PhantomJSDriverService.PHANTOMJS_CLI_ARGS, new
// String[] {
// "--web-security=false",
// "--ssl-protocol=any",
// "--ignore-ssl-errors=true"
// });
ArrayList<String> cliArgsCap = new ArrayList<String>();
cliArgsCap.add("--web-security=false");
cliArgsCap.add("--ssl-protocol=any");
cliArgsCap.add("--ignore-ssl-errors=true");
sCaps.setCapability(PhantomJSDriverService.PHANTOMJS_CLI_ARGS,
cliArgsCap);
// Control LogLevel for GhostDriver, via CLI arguments
sCaps.setCapability(
PhantomJSDriverService.PHANTOMJS_GHOSTDRIVER_CLI_ARGS,
new String[] { "--logLevel="
+ (sConfig.getProperty("phantomjs_driver_loglevel") != null ? sConfig
.getProperty("phantomjs_driver_loglevel")
: "INFO") });
// String driver = sConfig.getProperty("driver", DRIVER_PHANTOMJS);
// Start appropriate Driver
if (isUrl(driver)) {
sCaps.setBrowserName("phantomjs");
mDriver = new RemoteWebDriver(new URL(driver), sCaps);
} else if (driver.equals(DRIVER_FIREFOX)) {
mDriver = new FirefoxDriver(sCaps);
} else if (driver.equals(DRIVER_CHROME)) {
mDriver = new ChromeDriver(sCaps);
} else if (driver.equals(DRIVER_PHANTOMJS)) {
mDriver = new PhantomJSDriver(sCaps);
}
}
/**
* check whether input is a valid URL
*
* @author [email protected]
* @param urlString urlString
* @return true means yes, otherwise no.
*/
private boolean isUrl(String urlString) {
try {
new URL(urlString);
return true;
} catch (MalformedURLException mue) {
return false;
}
}
/**
* store webDrivers created
*/
private List<WebDriver> webDriverList = Collections
.synchronizedList(new ArrayList<WebDriver>());
/**
* store webDrivers available
*/
private BlockingDeque<WebDriver> innerQueue = new LinkedBlockingDeque<WebDriver>();
public WebDriverPool(int capacity) {
this.capacity = capacity;
}
public WebDriverPool() {
this(DEFAULT_CAPACITY);
}
/**
*
* @return
* @throws InterruptedException
*/
public WebDriver get() throws InterruptedException {
checkRunning();
WebDriver poll = innerQueue.poll();
if (poll != null) {
return poll;
}
if (webDriverList.size() < capacity) {
synchronized (webDriverList) {
if (webDriverList.size() < capacity) {
// add new WebDriver instance into pool
try {
configure();
innerQueue.add(mDriver);
webDriverList.add(mDriver);
} catch (IOException e) {
e.printStackTrace();
}
// ChromeDriver e = new ChromeDriver();
// WebDriver e = getWebDriver();
// innerQueue.add(e);
// webDriverList.add(e);
}
}
}
return innerQueue.take();
}
public void returnToPool(WebDriver webDriver) {
checkRunning();
innerQueue.add(webDriver);
}
protected void checkRunning() {
if (!stat.compareAndSet(STAT_RUNNING, STAT_RUNNING)) {
throw new IllegalStateException("Already closed!");
}
}
public void closeAll() {
boolean b = stat.compareAndSet(STAT_RUNNING, STAT_CLODED);
if (!b) {
throw new IllegalStateException("Already closed!");
}
for (WebDriver webDriver : webDriverList) {
logger.info("Quit webDriver" + webDriver);
webDriver.quit();
webDriver = null;
}
}
}
package us.codecraft.webmagic.downloader.selenium;
import org.apache.log4j.Logger;
import org.openqa.selenium.By;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Request;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.downloader.Downloader;
import us.codecraft.webmagic.selector.Html;
import us.codecraft.webmagic.selector.PlainText;
import java.io.Closeable;
import java.io.IOException;
import java.util.Map;
/**
* 使用Selenium呼叫瀏覽器進行渲染。目前僅支援chrome。<br>
* 需要下載Selenium driver支援。<br>
*
* @author [email protected] <br>
* Date: 13-7-26 <br>
* Time: 下午1:37 <br>
*/
public class SeleniumDownloader implements Downloader, Closeable {
private volatile WebDriverPool webDriverPool;
private Logger logger = Logger.getLogger(getClass());
private int sleepTime = 0;
private int poolSize = 1;
private static final String DRIVER_PHANTOMJS = "phantomjs";
/**
* 新建
*
* @param chromeDriverPath chromeDriverPath
*/
public SeleniumDownloader(String chromeDriverPath) {
System.getProperties().setProperty("webdriver.chrome.driver",
chromeDriverPath);
}
/**
* Constructor without any filed. Construct PhantomJS browser
*
* @author [email protected]
*/
public SeleniumDownloader() {
// System.setProperty("phantomjs.binary.path",
// "/Users/Bingo/Downloads/phantomjs-1.9.7-macosx/bin/phantomjs");
}
/**
* set sleep time to wait until load success
*
* @param sleepTime sleepTime
* @return this
*/
public SeleniumDownloader setSleepTime(int sleepTime) {
this.sleepTime = sleepTime;
return this;
}
@Override
public Page download(Request request, Task task) {
checkInit();
WebDriver webDriver;
try {
webDriver = webDriverPool.get();
} catch (InterruptedException e) {
logger.warn("interrupted", e);
return null;
}
logger.info("downloading page " + request.getUrl());
webDriver.get(request.getUrl());
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
WebDriver.Options manage = webDriver.manage();
Site site = task.getSite();
if (site.getCookies() != null) {
for (Map.Entry<String, String> cookieEntry : site.getCookies()
.entrySet()) {
Cookie cookie = new Cookie(cookieEntry.getKey(),
cookieEntry.getValue());
manage.addCookie(cookie);
}
}
/*
* TODO You can add mouse event or other processes
*
* @author: [email protected]
*/
WebElement webElement = webDriver.findElement(By.xpath("/html"));
String content = webElement.getAttribute("outerHTML");
Page page = new Page();
page.setRawText(content);
page.setHtml(new Html(content, request.getUrl()));
page.setUrl(new PlainText(request.getUrl()));
page.setRequest(request);
webDriverPool.returnToPool(webDriver);
return page;
}
private void checkInit() {
if (webDriverPool == null) {
synchronized (this) {
webDriverPool = new WebDriverPool(poolSize);
}
}
}
@Override
public void setThread(int thread) {
this.poolSize = thread;
}
@Override
public void close() throws IOException {
webDriverPool.closeAll();
}
}
0、官網參考資料:
Selenium 是Web的自動化測試工具,可以模擬使用者與瀏覽器互動,進行存取網站。
Selenium是一個瀏覽器自動化的大型專案。
它提供用於模擬使用者與瀏覽器互動的擴充套件、用於擴充套件瀏覽器分配的分發伺服器,以及用於實現W3C WebDriver 規範的基礎結構,使您可以為所有主要 Web 瀏覽器編寫可互換的程式碼。Selenium 的核心是WebDriver,它是一個編寫指令集的介面,可以在許多瀏覽器中互換執行。
自動化測試:自動化測試工具,可以模擬使用者與瀏覽器互動,進行存取網站。
爬蟲:因為Selenium可以控制瀏覽器傳送請求,並獲取網頁資料,因此可以應用於爬蟲領域。
Selenium 可以根據我們的指令,讓瀏覽器自動載入頁面,獲取需要的資料,甚至頁面截圖,或者判斷網站上某些動作是否發生。
Selenium是一個Web的自動化測試工具,最初是為網站自動化測試而開發的,Selenium 可以直接執行在瀏覽器上,它支援所有主流的瀏覽器。
Selenium 自己不帶瀏覽器,不支援瀏覽器的功能,它需要與第三方瀏覽器結合在一起才能使用。
PhantomJS 是一個基於Webkit的「無介面」(headless)瀏覽器,它會把網站載入到記憶體並執行頁面上的 JavaScript,因為不會展示圖形介面,所以執行起來比完整的瀏覽器要高效。
如果我們把 Selenium 和 PhantomJS 結合在一起,就可以執行一個非常強大的網路爬蟲了,這個爬蟲可以處理 JavaScrip、Cookie、headers,以及任何我們真實使用者需要做的事情。
注意 :chromedriver的版本要與你使用的chrome版本對應!
chromedriver版本 支援的Chrome版本 v2.46 v71-73 v2.45 v70-72 v2.44 v69-71 v2.43 v69-71 v2.42 v68-70 v2.41 v67-69 v2.40 v66-68 v2.39 v66-68 v2.38 v65-67 v2.37 v64-66 v2.36 v63-65 v2.35 v62-64 v2.34 v61-63 v2.33 v60-62 v2.32 v59-61 v2.31 v58-60 v2.30 v58-60 v2.29 v56-58 v2.28 v55-57 v2.27 v54-56 v2.26 v53-55 v2.25 v53-55 v2.24 v52-54 v2.23 v51-53 v2.22 v49-52 v2.21 v46-50 v2.20 v43-48 v2.19 v43-47 v2.18 v43-46 v2.17 v42-43 v2.13 v42-45 v2.15 v40-43 v2.14 v39-42 v2.13 v38-41 v2.12 v36-40 v2.11 v36-40 v2.10 v33-36 v2.9 v31-34 v2.8 v30-33 v2.7 v30-33 v2.6 v29-32 v2.5 v29-32 v2.4 v29-32
public class FirstScriptTest {
@Test
public void eightComponents() {
//通過DesiredCapabilities、options 可以給driver 設定一個選項,例如代理,禁止載入圖片、去掉介面模式等
//參考:ChromeDriver:https://sites.google.com/a/chromium.org/chromedriver/capabilities
String downloadsPath = "d:\\data\\downloads";
HashMap<String, Object> chromePrefs = new HashMap<String, Object>();
chromePrefs.put("download.default_directory", downloadsPath);
ChromeOptions options = new ChromeOptions();
Proxy proxy = new Proxy();
// 需要增加設定ssl協定
proxy.setHttpProxy(VpnServerUtils.getVpnServer()).setSslProxy(VpnServerUtils.getVpnServer());
// proxy.setHttpProxy(VpnServerUtils.getVpnServer());
options.setCapability("proxy",proxy);
System.out.println("~~~~~~~~~~~~~~~~~proxy: " + proxy.getHttpProxy());
options.setExperimentalOption("prefs", chromePrefs);
DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability(ChromeOptions.CAPABILITY, options);
WebDriver driver = new ChromeDriver(caps);
//瀏覽器驅動器請求載入頁面
driver.get("https://www.selenium.dev/selenium/web/web-form.html");
//查詢元素
String title = driver.getTitle();
assertEquals("Web form", title);
driver.manage().timeouts().implicitlyWait(Duration.ofMillis(500));
WebElement textBox = driver.findElement(By.name("my-text"));
WebElement submitButton = driver.findElement(By.cssSelector("button"));
textBox.sendKeys("Selenium");
submitButton.click();//點選事件
WebElement message = driver.findElement(By.id("message"));
String value = message.getText();
assertEquals("Received!", value);
//結束對談
driver.quit();
}
}
如果本文對你有幫助的話記得給一樂點個贊哦,感謝!
本文來自部落格園,作者:一樂樂,轉載請註明原文連結:https://www.cnblogs.com/shan333/p/17203373.html