Selenium Webdriver重新使用已開啟的瀏覽器例項(Chrome版)
阿新 • • 發佈:2019-01-11
昨天百度了半天關於Selenium Webdriver怎樣重新使用已開啟的瀏覽器的問題,就找到了這麼位大佬的文章:
因為沒積分,程式碼是在這下的
把程式碼下下來研究了半天,勉強算是改了個Chrome版的,能夠在已經開啟的Chrome瀏覽器上繼續操作,但是有很大缺陷,程式碼執行時不會報一些異常了,所以發出來希望有大佬幫忙修改一下,註解是我自己的理解,可能會有錯
一共三個工具類,第一個是修改的ChromeDriver,程式碼如下
import static org.openqa.selenium.remote.CapabilityType.PROXY; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import org.openqa.selenium.Capabilities; import org.openqa.selenium.ImmutableCapabilities; import org.openqa.selenium.MutableCapabilities; import org.openqa.selenium.Proxy; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.remote.Command; import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.Response; public class MyChromeDriver extends ChromeDriver { // 用於設定capabilities private Capabilities myCapabilities; public MyChromeDriver(String sessionID,String localserver) { mystartClient(localserver); mystartSession(sessionID); } //重寫startSession方法,可以防止呼叫父級startSession方法而導致開啟多個瀏覽器 @Override protected void startSession(Capabilities desiredCapabilities) { // Do Nothing } //改寫的startClient方法,用於傳入localserver(即瀏覽器的地址),配合sessionID能找出在用的瀏覽器 protected void mystartClient(String localserver) { HttpCommandExecutor delegate = null; try { URL driverserver = new URL(localserver); delegate = new MyHttpCommandExecutor(driverserver); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } setCommandExecutor(delegate); System.out.println("Connect to the existing browser"); } //改寫的startSession方法,用於傳入sessionID,配合localserver能找出在用的瀏覽器 protected void mystartSession(String sessionID) { if (!sessionID.isEmpty()) { super.setSessionId(sessionID); } Command command = new Command(super.getSessionId(), DriverCommand.STATUS); Response response; try { response = ((MyHttpCommandExecutor)getCommandExecutor()).execute(command); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); System.out.println("Can't use this Session"); return; } //列印系統資訊 System.out.println("response.getValue()" + response.getValue()); if (response.getValue() instanceof Exception) { ((Exception)response.getValue()).printStackTrace(); } //為了能執行Script this.myCapabilities = dropCapabilities(new ChromeOptions()) ; } private static Capabilities dropCapabilities(Capabilities capabilities) { if (capabilities == null) { return new ImmutableCapabilities(); } MutableCapabilities caps = new MutableCapabilities(capabilities); // Ensure that the proxy is in a state fit to be sent to the extension Proxy proxy = Proxy.extractFrom(capabilities); if (proxy != null) { caps.setCapability(PROXY, proxy); } return caps; } @Override public void quit() { try { execute(DriverCommand.QUIT); } catch (Exception e) { e.printStackTrace(); } } public Capabilities getCapabilities() { return myCapabilities; } }
第二個修改的HttpCommandExecutor,應該是用來設定CommandCodec與ResponseCodec的,不大清楚
import static org.openqa.selenium.remote.DriverCommand.GET_ALL_SESSIONS; import static org.openqa.selenium.remote.DriverCommand.NEW_SESSION; import static org.openqa.selenium.remote.DriverCommand.QUIT; import java.io.IOException; import java.net.URL; import org.openqa.selenium.NoSuchSessionException; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.UnsupportedCommandException; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.Command; import org.openqa.selenium.remote.CommandCodec; import org.openqa.selenium.remote.Dialect; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.HttpSessionId; import org.openqa.selenium.remote.ProtocolHandshake; import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.ResponseCodec; import org.openqa.selenium.remote.http.HttpClient; import org.openqa.selenium.remote.http.HttpRequest; import org.openqa.selenium.remote.http.HttpResponse; import org.openqa.selenium.remote.http.W3CHttpCommandCodec; import org.openqa.selenium.remote.http.W3CHttpResponseCodec; import org.openqa.selenium.remote.internal.ApacheHttpClient; //該類是為了設定CommandCodec與ResponseCodec,父類這些預設為空 public class MyHttpCommandExecutor extends HttpCommandExecutor{ private CommandCodec<HttpRequest> mycommandCodec; private ResponseCodec<HttpResponse> myresponseCodec; private final HttpClient myclient; public MyHttpCommandExecutor(URL addressOfRemoteServer) { super(addressOfRemoteServer); initCodec(); this.myclient = new ApacheHttpClient.Factory().createClient(addressOfRemoteServer); } private void initCodec() { mycommandCodec = new W3CHttpCommandCodec(); myresponseCodec = new W3CHttpResponseCodec(); } @SuppressWarnings("deprecation") public Response execute(Command command) throws IOException { if (command.getSessionId() == null) { if (QUIT.equals(command.getName())) { return new Response(); } if (!GET_ALL_SESSIONS.equals(command.getName()) && !NEW_SESSION.equals(command.getName())) { throw new NoSuchSessionException("Session ID is null. Using WebDriver after calling quit()?"); } } if (NEW_SESSION.equals(command.getName())) { if (mycommandCodec != null) { throw new SessionNotCreatedException("Session already exists"); } ProtocolHandshake handshake = new ProtocolHandshake(); ProtocolHandshake.Result result = handshake.createSession(myclient, command); Dialect dialect = result.getDialect(); mycommandCodec = dialect.getCommandCodec(); myresponseCodec = dialect.getResponseCodec(); return result.createResponse(); } if (mycommandCodec == null || myresponseCodec == null) { throw new WebDriverException("No command or response codec has been defined. Unable to proceed"); } HttpRequest httpRequest = mycommandCodec.encode(command); try { HttpResponse httpResponse = myclient.execute(httpRequest); Response response = myresponseCodec.decode(httpResponse); if (response.getSessionId() == null) { if (httpResponse.getTargetHost() != null) { response.setSessionId(HttpSessionId.getSessionId(httpResponse.getTargetHost())); } else { // Spam in the session id from the request response.setSessionId(command.getSessionId().toString()); } } if (QUIT.equals(command.getName())) { myclient.close(); } return response; } catch (UnsupportedCommandException e) { if (e.getMessage() == null || "".equals(e.getMessage())) { throw new UnsupportedOperationException( "No information from server. Command name was: " + command.getName(), e.getCause()); } throw e; } } }
然後是個傳參的類,水平太差,只能弄了個檔案儲存資料,希望有大佬能優化一下
package su.jian; import java.io.BufferedReader; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class URLAndSession { public String getSessionID() throws IOException { FileReader fr = new FileReader("sessionID.txt"); BufferedReader br = new BufferedReader(fr); String sessionID = br.readLine(); fr.close(); return sessionID; } public void setSessionID(String sessionID) throws IOException { FileWriter fw = new FileWriter("sessionID.txt"); fw.write(sessionID); fw.close(); } public String getLocalserver() throws IOException { FileReader fr = new FileReader("localserver.txt"); BufferedReader br = new BufferedReader(fr); String localserver = br.readLine(); fr.close(); return localserver; } public void setLocalserver(String localserver) throws IOException { FileWriter fw = new FileWriter("localserver.txt"); fw.write(localserver); fw.close(); } }
最後是用例,能夠在第一個開啟的瀏覽器的同一個標籤開啟新網頁,也可以定位元素,但是不會報異常
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.HttpCommandExecutor;
public class TestCase {
private static URLAndSession uas = new URLAndSession();
static {
System.setProperty("webdriver.chrome.driver", "D:/chromedriver_win32/chromedriver.exe");
}
public static void main(String[] args) throws IOException {
//這兒沒法用WebDriver定義,因為會沒有getSessionId方法
ChromeDriver driver = new ChromeDriver();
//獲取已開啟瀏覽器的sessionId
String sessionId = driver.getSessionId().toString();
System.out.println("sessionId:"+sessionId);
//獲取已開啟瀏覽器的URL
String url = ((HttpCommandExecutor)(driver.getCommandExecutor())).getAddressOfRemoteServer().toString();
System.out.println(url);
//儲存資料
uas.setSessionID(sessionId);
uas.setLocalserver(url);
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
driver.get("http://www.baidu.com");
}
@Test
public void testName() throws Exception {
System.out.println(uas.getSessionID()+"==========="+uas.getLocalserver());
//構造器獲取sessionId和URL
ChromeDriver driver = new MyChromeDriver(uas.getSessionID(),uas.getLocalserver());
driver.get("http://www.sohu.com/");
}
}
望大佬修改,能給個現成的就更好了