Java Selenium抓取网页

最近自己在做一个项目使用Selenium抓取数据,发现升级Google Chrome 84版本会出现 被检测出来使用 就不给你返回数据,导致无法使用,抓狂了一段时间没有解决方案,以下都是亲测成功总结,百度搜索都是千遍一律的结果,有许多坑。

防止网站检测出Selenium的window.navigator.webdriver属性

1.升级Selenium 版本

       

            org.seleniumhq.selenium

            selenium-java

            4.0.0-alpha-6

       


java.lang.NoSuchMethodError: 'byte[] kotlin.collections.ArraysKt.copyInto

升级版本的时候会遇到包版本冲突的问题,解决方法:

       

            org.jetbrains.kotlin

            kotlin-stdlib

            1.3.70

       



2. 使用官方插件CDP命令 屏蔽window.navigator.webdriver属性值

ChromeOptions options =new ChromeOptions();

//不提示“Chrome正受到自动测试软件控制” 

options.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation") );

options.setExperimentalOption("useAutomationExtension", false);

Map map =new HashMap();

map.put("source","Object.defineProperties(navigator, {webdriver:{get:()=>undefined}})");

driver.executeCdpCommand("Page.addScriptToEvaluateOnNewDocument",map);


3. ChromeDriver 对应本地浏览器的版本




selenium是一个自动化网页测试业务流程工具,也可以用来爬取网页数据。

谷歌驱动下载 ChromeDriver 2.35   

我本地Google Chrome 84.0.4147.125(正式版本) (64 位)

也可以用,但是selenium升级后用不了CDP命令。


http://npm.taobao.org/mirrors/chromedriver/

下载chromeDriver:http://chromedriver.storage.googleapis.com/index.html

            org.seleniumhq.selenium

            selenium-java

            3.141.59

selenium 依赖了com.google.guava 25.0-jre注意重复依赖问题

重复依赖报错:

java.lang.IllegalAccessError: tried to access method com.google.common.util.concurrent.SimpleTimeLimiter.(Ljava/util/concurrent/ExecutorService;)V

解决方法 找出低版本的另一个依赖排除com.google.guava依赖:

    com.google.guava

    guava

我的冲突就是io.springfox包含了com.google.guava 20.0,该项目的pom.xml依赖下加上以上的语句来排除依赖


Selenium 3.0使用firefox

https://github.com/mozilla/geckodriver/releases



###java###

private static WebDriverdriver;

private static ChromeDriverServiceservice;

public static void createAndStartService() {

    service =new ChromeDriverService.Builder()

    .usingDriverExecutable(new File("C:\\Program Files (x86)\\webDriver\\chromedriver.exe"))

    .usingAnyFreePort()

    .build();

     try {

            service.start();

     }catch (IOException e) {

            e.printStackTrace();

     }

}

public static void createDriver(URL url, String urlPath){

    driver =new RemoteWebDriver(url, DesiredCapabilities.chrome());

    //driver.get(urlPath);  //打开一个页面访问

    try {

        /**

        * WebDriver自带了一个智能等待的方法。 dr.manage().timeouts().implicitlyWait(arg0, arg1);

        * Arg0:等待的时间长度,int 类型 ; Arg1:等待时间的单位 TimeUnit.SECONDS 一般用秒作为单位。

        */

        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

    } catch (Exception e) {

        e.printStackTrace();

    }

    //获取当前浏览器的信息

    System.out.println("Title:" +driver.getTitle());

    System.out.println("currentUrl:" +driver.getCurrentUrl());

}


private void createDriver(URL url, String urlPath){

try {

        if(url ==null){

            url=service.getUrl();

        }

        ChromeOptions options =new ChromeOptions();

        //不提示“Chrome正受到自动测试软件控制”

        options.setExperimentalOption("excludeSwitches", new String[]{"enable-automation"});

        options.setExperimentalOption("useAutomationExtension", false);

        //driver = new ChromeDriver(service, options);

        //driver = new RemoteWebDriver(url, DesiredCapabilities.chrome());

        //不加载图片,加快访问速度

        Map prefs =new HashMap();

        prefs.put("profile.managed_default_content_settings.images", 2);

        options.setExperimentalOption("prefs", prefs);

        //使用本地的Google浏览器,一次只能打开一个

        options.addArguments("user-data-dir=C:/Users/Administrator/AppData/Local/Google/Chrome/User Data");

        driver =new ChromeDriver(service, options);

        //解决,对window.navigator.webdriver的检测机制

        JavascriptExecutor executor = (JavascriptExecutor)driver;

        executor.executeScript("Object.defineProperties(navigator, {webdriver:{get:()=>undefined}});");

        if(StringUtils.isNotEmpty(urlPath)) {

                driver.get(urlPath);

        }

/**

* WebDriver自带了一个智能等待的方法。 dr.manage().timeouts().implicitlyWait(arg0, arg1);

* Arg0:等待的时间长度,int 类型 ; Arg1:等待时间的单位 TimeUnit.SECONDS 一般用秒作为单位。

*/

        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

    }catch (Exception e) {

e.printStackTrace();

    }

}



参数设置

ChromeOptions options =new ChromeOptions();

//不提示“Chrome正受到自动测试软件控制”  Collections.singletonList("enable-automation")

//options.setExperimentalOption("excludeSwitches", new String[]{"enable-automation"});

//options.setExperimentalOption("useAutomationExtension", false);

//打开cmd 进入到Google Chrome目录下运行如下命令:

//chrome.exe --remote-debugging-port=9222 --user-data-dir="F:\selenum\AutomationProfile"

//options.setExperimentalOption("debuggerAddress","127.0.0.1:9222");

//设置代理

//options.addArguments("--proxy-server=http://127.0.0.1:8080");

//driver = new RemoteWebDriver(url, DesiredCapabilities.chrome());

//不加载图片,加快访问速度 1允许  2禁止

//Map prefs = new HashMap();

//prefs.put("profile.managed_default_content_settings.images", 1);

//options.setExperimentalOption("prefs", prefs);

//使用本地的Google浏览器,一次只能打开一个

//options.addArguments("user-data-dir=C:/Users/Administrator/AppData/Local/Google/Chrome/User Data");



//关闭驱动并退出

public static void doCloseQuit(){

        if(driver != null) {

            driver.close();

            driver.quit();

        }

    }

driver.findElement(By.id("login_id")).clear(); //获取id是login_id的元素,并清除内容

driver.findElement(By.id("login_id")).sendKeys("xxx"); //获取id是login_id的元素,并输入xxx内容

driver.findElement(By.id("continueBtn")).click(); //获取id是continueBtn的元素,并模拟执行点击事件

.sendKeys(Keys.ENTER);  //相当于按键盘上的Enter(回车)


//骚操作By.xpath,任意的去匹配你要获取的元素,下面就是获取id是rptBody元素内的div内的table元素

By by = By.xpath(".//*[@id='rptBody']/div/table");

WebElement tableElement =driver.findElement(by);


这种写法是如果在div内有多个table获取的是第一个table元素

By by = By.xpath(".//*[@id='rptBody']/div/table[1]");


//同级元素

By by = By.xpath(".//input[@id='ids']/../span");


//执行js脚本方法

String jString="Login()";

((JavascriptExecutor)driver).executeScript(jString);


下拉选择框获取选中的值

WebElement selectWebElement = driver.findElement(By.id("_jt_page_size"));

Select select = new Select(selectWebElement);

String s = select.getFirstSelectedOption().getText();



//如果你需要获取 iframe 内的元素需要一下流程才能获取:

//进入到 iframe 内

WebElement iframe =driver.findElement(By.id("iframe"));

driver.switchTo().frame(iframe);


//获取iframe 内元素的操作

...


// 回到主窗口

driver.switchTo().defaultContent();


/**

* 浏览器后台运行,向下滑动

* @param url

* @return

*/

public static DocumentgetDocument(String url){

Document doc =null;

    //可使用的浏览器有:IE浏览器(webdriver.ie.driver)

//火狐浏览器  (webdriver.gecko.driver)

//谷歌浏览器 (webdriver.chrome.driver)

//                  是使用那个浏览器                                  chromedriver所在的位置

    System.setProperty("webdriver.chrome.driver", "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chromedriver.exe");

    // InternetExplorerDriver()  浏览器

// FirefoxDriver()            火狐浏览器

//谷歌浏览器

    WebDriver driver =null;

    //创建chrome参数对象

    ChromeOptions options =new ChromeOptions();

    //浏览器后台运行

    options.addArguments("headless");

    driver =new ChromeDriver(options);

    driver.get(url);

    //等待几秒

    try {

//向下滚动  方法一

//JavascriptExecutor js = (JavascriptExecutor)driver;

//js.executeScript("scrollTo(0,20000)");

//向下滚动 方法二

        ((JavascriptExecutor)driver).executeScript("scrollTo(0,10000)");

        Thread.sleep(20000);

    }catch (InterruptedException e) {

        e.printStackTrace();

    }

doc = Jsoup.parse(driver.getPageSource());

    //关闭浏览器

    driver.close();

    driver.quit();

    return doc;

}

你可能感兴趣的:(Java Selenium抓取网页)