欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java爬虫——Selenium Java详解及案例

程序员文章站 2022-06-05 18:53:55
...

一些基础的知识可以通过以下链接先了解:
https://www.jianshu.com/p/20526e2ac3b1

import com.bbt.companyreg.skuhelper.service.HttpProxyIPPoolService;
import com.bbt.companyreg.skuhelper.service.impl.HttpProxyIPPoolServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

/**
 * Created by wuming on 2020/6/10 11:03
 */
@Slf4j
public class WebDriverUtil {
    private static ChromeDriver webDriver;
    public static String ip;
    public static ChromeDriver getWebDriver() {
        String driver = null;
        if(isOSWindow()){
            driver = "D:\\chromedriver\\chromedriver.exe";
        }else{
            driver = "/usr/bin/driver/chromedriver";
        }
        System.setProperty("webdriver.chrome.driver", driver);
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized"); // 启动时自动最大化窗口
        options.addArguments("--disable-popup-blocking"); // 禁用阻止弹出窗口
        options.addArguments("no-sandbox"); // 启动无沙盒模式运行
        options.addArguments("disable-extensions"); // 禁用扩展
        options.addArguments("no-default-browser-check"); // 默认浏览器检查
        options.setHeadless(Boolean.TRUE);//设置chrome 无头模式
        options.addArguments("--headless");//不用打开图形界面。
        //这里设置访问的ip
        options.addArguments("--proxy-server=http://" + ip);
        webDriver = new ChromeDriver(options);
        //  webDriver.manage().window().maximize();
        // 与浏览器同步非常重要,必须等待浏览器加载完毕,隐式等待30s
        webDriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        //设置页面超时时间,有时候浏览器会处于假死状态,设置这个解决。
        webDriver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS);
        return webDriver;
    }

    public static void closeDriver() {
        webDriver.close();
        webDriver = null;
    }

    //判断当前是否linux系统
    public static boolean isOSWindow() {
        Properties prop = System.getProperties();
        String os = prop.getProperty("os.name");
        if (os != null && os.toLowerCase().indexOf("windows") > -1) {
            return true;
        } else {
            return false;
        }
    }


    public static String getIp(){
        String ip = null;
        Integer port = null;
        for(int i=0;i<6;i++){
            HttpProxyIPPoolService httpProxyIPPoolService = new HttpProxyIPPoolServiceImpl();
            List<HttpProxyIPPoolServiceImpl.IPData> ips = httpProxyIPPoolService.getNextIP();
            HttpProxyIPPoolServiceImpl.IPData ipData = ips.get(0);
            port = Integer.valueOf(ipData.getPort());
            ip = ipData.getIp();
            if(test(ip, port)){
                return ip+":"+port;
            }
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return ip+":"+port;
    }
    
    //可以通过这种方式筛选出速度比较快的ip
    private static boolean test(String ip, Integer port) {
        try {
           CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet("www.baidu.com");
            HttpHost proxy = new HttpHost(ip, port);
            RequestConfig requestConfig = RequestConfig.custom()
                    .setProxy(proxy)
                    .setConnectTimeout(200)
                    .setSocketTimeout(200)
                    .setConnectionRequestTimeout(200)
                    .build();
            httpGet.setConfig(requestConfig);
//            //设置请求头信息
//            httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like " +
//                    "Gecko) Chrome/62.0.3202.94 Safari/537.36");
            CloseableHttpResponse response = httpClient.execute(httpGet);
            if (response == null) {
                log.warn("当前ip不可用:重新获取---"+ip);
                return false;
            } else {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    return true;
                }
            }
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        log.warn("当前ip不可用:"+ip);
        return false;
    }
//显示等待的方式让这两个按钮加载完毕
    private void loadElement(){
        (new WebDriverWait(webDriver,10))
                .until(ExpectedConditions.elementToBeClickable(By.className(skuBtn)));
        (new WebDriverWait(webDriver,10))
                .until(ExpectedConditions.elementToBeClickable(By.className(skuActionBtn)));
    }

显示等待,隐式等待和强制等待的区别:

在实际使用selenium时,等待下个等待定位的元素出现,特别是web端加载的过程,都需要用到等待,而等待方式的设置是保证脚本稳定有效运行的一个非常重要的手段,在selenium中(appium通用)常用的等待分为显示等待WebDriverWait()、隐式等待implicitly_wait()、强制等待sleep()三种,下面我们就分别介绍一下这三种等待的区别
sleep(): 强制等待,设置固定休眠时间。后脚本的执行过程中执行 sleep()后线程休眠,而另外两种线程不休眠。
implicitly_wait():隐式等待,是设置的全局等待。设置等待时间,是对页面中的所有元素设置加载时间,如果超出了设置时间的则抛出异常。隐式等待可以理解成在规定的时间范围内,浏览器在不停的刷新页面,直到找到相关元素或者时间结束。
WebDriverWait():显示等待,是针对于某个特定的元素设置的等待时间,在设置时间内,默认每隔一段时间检测一次当前页面某个元素是否存在,如果在规定的时间内找到了元素,则直接执行,即找到元素就执行相关操作,如果超过设置时间检测不到则抛出异常。默认检测频率为0.5s,默认抛出异常为:NoSuchElementException。

注意:
1.Java使用chromedriver的时候,同一个时间内只能够打开一个虚拟浏览器,不能使用多线程的方式同时打开多个chrome。

2.访问的频率也不能太快,要适当使用sleep降低访问频率,否则会被网站监测出来,网址很快被封。

3.当我们在一段时间内多次去爬取同一个网站的数据的时候,我们的ip可能会被ban,此时我们需要用到代理ip,使用一些免费的代理服务器的话,网络可能不稳定。此时可以去网上找些付费的,例如我之前使用过的小象代理。每个月也就100多。

public class HttpProxyIPPoolServiceImpl implements HttpProxyIPPoolService {
	private static String IP_URL = "https://api.xiaoxiangdaili.com/ip/get";
	private static String appKey="";
	private static String appSecret="";
	private static String cnt = "5";
	private static String wt = "json";

	@Override
	public List<IPData> getNextIP() {
		String responseJson = null;
		try {
			responseJson = Jsoup.connect(IP_URL).method(Connection.Method.GET)
					.header("Content-Type", "application/json;charset=UTF-8").data("appKey", appKey, "appSecret", appSecret, "cnt", cnt, "wt", wt)
					.ignoreHttpErrors(true).ignoreContentType(true).timeout(2000).get().text();
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		}
		log.info("responseJson:" + responseJson);

		XiaoXiangResultDto result = JSONObject.parseObject(responseJson, XiaoXiangResultDto.class);
		log.info("result IP:" + result.getData().get(0).getIp() + ", port:" + result.getData().get(0).getPort() + ", during:" + result.getData().get(0).getDuring());
		return result.getData();
	}

	public static class IPData {
		private String ip;
		private String port;
		private String realIp;
		private int during;
		public String getIp() {
			return ip;
		}
		public void setIp(String ip) {
			this.ip = ip;
		}
		public String getPort() {
			return port;
		}
		public void setPort(String port) {
			this.port = port;
		}
		public String getRealIp() {
			return realIp;
		}
		public void setRealIp(String realIp) {
			this.realIp = realIp;
		}
		public int getDuring() {
			return during;
		}
		public void setDuring(int during) {
			this.during = during;
		}
	}

	@Data
	private static class XiaoXiangResultDto {
		private int code;
		private boolean success;
		private String msg;
		private List<IPData> data;
		public int getCode() {
			return code;
		}
		public void setCode(int code) {
			this.code = code;
		}
		public boolean isSuccess() {
			return success;
		}
		public void setSuccess(boolean success) {
			this.success = success;
		}
		public String getMsg() {
			return msg;
		}
		public void setMsg(String msg) {
			this.msg = msg;
		}
		public List<IPData> getData() {
			return data;
		}
		public void setData(List<IPData> data) {
			this.data = data;
		}
	}
相关标签: selenium java