使用selenium 接管 已打开的浏览器

在使用selenium进行自动化测试中我们有时会遇到这样的情况:

​ 我们需要手动打开浏览器,进入到所需的页面,执行一些手动任务,如输入表单、输入验证码,登陆成功后,然后再开始运行自动化脚本。

这种情况下如何使用selenium来接管先前已打开的浏览器呢?

这里给出Google Chrome浏览器的解决方案。

我们可以利用Chrome DevTools协议。它允许客户检查和调试Chrome浏览器。

打开cmd,在命令行中输入命令:

chrome.exe –remote-debugging-port=9222 –user-data-dir=“C:\selenum\AutomationProfile”

对于-remote-debugging-port值,可以指定任何打开的端口。

对于-user-data-dir标记,指定创建新Chrome配置文件的目录。它是为了确保在单独的配置文件中启动chrome,不会污染你的默认配置文件。

还有,不要忘了在环境变量中PATH里将chrome的路径添加进去。

此时会打开一个浏览器页面,我们输入百度网址,我们把它当成一个已存在的浏览器:

img

现在,我们需要接管上面的浏览器。新建一个python文件,运行以下代码:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
chrome_driver = "C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe"
driver = webdriver.Chrome(chrome_driver, chrome_options=chrome_options)
print(driver.title)

会发现打印出了 “百度一下,你就知道” 的网页标题。这样我们就实现了对一个已打开的浏览器的控制。

import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.net.Socket;


public class TestMoveVerificationCode {
    private static String baseUrl = "http://tiaojie.court.gov.cn/fayuan";

    public static void main(String[] args) {

//        int port = NetUtils.getAvailablePort();
        int port = 9224;
        System.out.println("端口:"+port);
        //用户数据文件夹
        String userDataDir="C:\\selenum\\"+port;
        File dataDir = new File(userDataDir);

        try {
            //设置环境变量,将chrome.exe所在的文件夹C:\Program Files (x86)\Google\Chrome\Application\添加到path中
            // C:\Program Files (x86)\Google\Chrome\Application\chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\selenum\AutomationProfile"
            String cmd ="cmd /c start /MAX chrome.exe --remote-debugging-port="+port+" --user-data-dir=\""+userDataDir+"\"";
            Process process = Runtime.getRuntime().exec(cmd);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("浏览器已打开……");

        System.setProperty("webdriver.chrome.driver","C:\\windows\\chromedriver.exe");

        ChromeOptions options = new ChromeOptions();
        options.setExperimentalOption("debuggerAddress", "127.0.0.1:"+port);

        WebDriver driver = new ChromeDriver(options);

        driver.get(baseUrl);
        //等待滑动验证码加载完成
        new WebDriverWait(driver, 10).until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//span[contains(.,'加载中')]")));
        //等待元素出现
        WebElement draggable = (new WebDriverWait( driver, 10)).until(new ExpectedCondition<WebElement>(){
                                                                        @Override
                                                                        public WebElement apply(WebDriver d){
                                                                            return d.findElement(By.className("btn_slide"));
                                                                        }
                                                                    }
        );
        WebElement userName = driver.findElement(By.id("userName"));
        userName.sendKeys("1111111");
        WebElement password = driver.findElement(By.id("password"));
        password.sendKeys("12222");
//        WebElement draggable = driver.findElement(By.className("btn_slide"));
        // 声明action对象
        Actions action = new Actions(driver);
        // clickAndHold鼠标左键按下draggable元素不放
        action.clickAndHold(draggable).build().perform();
        //确保每次拖动的像素不同,故而使用随机数。防止反爬虫拦截
        try {
            action.moveByOffset((int)(Math.random()*200)+80, 0);
            Thread.sleep(100);
            action.moveByOffset((int)(Math.random()*200)+80, 0);
            Thread.sleep(100);
            action.moveByOffset((int)(Math.random()*200)+80, 0);
            Thread.sleep(100);
            action.moveByOffset((int)(Math.random()*200)+80, 0);
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        action.moveByOffset(280, 0);
        //释放
        action.release();
        //执行
        action.perform();
        //等待元素消失
//        new WebDriverWait(driver, 10).until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//span[contains(.,'加载中')]")));
        WebElement loginBtn = driver.findElement(By.id("loginBtn"));
        loginBtn.click();
    }
}
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetAddress;
import java.util.Random;
import java.net.Socket;

@Slf4j
public class NetUtils {

    /**
     * 测试本机端口是否被使用
     * @param port
     * @return
     */
    public static boolean isLocalPortUsing(int port){
        boolean flag = true;
        try {
            //如果该端口还在使用则返回true,否则返回false,127.0.0.1代表本机
            flag = isPortUsing("127.0.0.1", port);
        } catch (Exception e) {
        }
        return flag;
    }
    /***
     * 测试主机Host的port端口是否被使用
     * @param host
     * @param port
     */
    public static boolean isPortUsing(String host,int port)  {
        boolean flag = false;
        try {
            InetAddress Address = InetAddress.getByName(host);
            //建立一个Socket连接
            Socket socket = new Socket(Address,port);
            flag = true;
        } catch (IOException e) {
            //log.info(e.getMessage(),e);
        }
        return flag;
    }

    /**
     * 由于本机上安装了mysql,采用3306端口去验证
     * @param args
     */
    public static void main(String args[]){
        int testPost =3306;
        if(isLocalPortUsing(testPost)){
            System.out.println("端口 "+testPost+" 已被使用");
        }else{
            System.out.println("端口 "+testPost+"未使用");
        }
    }
    /**
     * 获取可用端口
     * @return
     */
    public static int getAvailablePort(){
        int max = 65535;
        int min = 2000;

        Random random = new Random();
        int port = random.nextInt(max)%(max-min +1) + min;
        boolean using = NetUtils.isLocalPortUsing(port);
        if(using){
            return  getAvailablePort();
        }else{
            return  port;
        }
    }
}