赞
踩
一些基础的知识可以通过以下链接先了解:
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; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。