java+selenium自动化抓取51la数据
初衷
前端埋点51la,进行网站统计。51la没有对外提供数据同步接口,并且大量广告掺杂。
所以需要把51la数据抓取整理后进行展示。当然还有更多办法,想学习一下selenium~
环境依赖
我擅长使用java所以用java+selenium+火狐进行数据抓取同步;
没有找到谷歌最新版对应的驱动 所以使用火狐。
selenium3.8x兼容测试稳定,4.x不太稳定你可以再试试
- java8;
- springboot;
- selenium;
- 火狐驱动;
- 火狐浏览器83,驱动0.28.0 (2020-11-03),selenium-java 3.8.1
- 精简pom:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.4.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.8.1</version>
</dependency>
</dependencies>
demo上代码
第一步肯定要先试下selenium是否正常运行了~
//设置环境value=火狐驱动本地地址,研发生产环境可通过File.separator动态加载
System.setProperty("webdriver.gecko.driver", "D:/geckodriver.exe");
WebDriver driver = new FirefoxDriver(); //实现Firefox
driver.manage().window().maximize(); //最大化
driver.manage().deleteAllCookies(); //清理cookies
// 与浏览器同步非常重要,必须等待浏览器加载完毕
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://user.51.la/login?xxxxx");//login_url =你的登录地址
String title = driver.getTitle();//获取html标题
System.out.println(title);//输出;
//如果输出正常说明selenium运行成功;
第二步就要模拟登陆啦~
//当然可以使用By.path....很多种方法~
//value=cgy 是账号密码,替换你自己的哦!
driver.findElements(By.className("el-input__inner")).get(0).sendKeys("cgy");
driver.findElements(By.className("el-input__inner")).get(1).sendKeys("cgy");
driver.findElements(By.tagName("button")).get(0).click();
//value = cgy 是登陆成功后右上角的元素值哦,替换自己的。
//1校验登录是否成功,如果找到元素说明登陆成功,如果没有登陆成功就会抛出异常,catch就可以了
WebElement element = driver.findElement(By.xpath("//*[contains(.,'cgy')]"));
//2校验模式是否点击成功,如果没有登陆成功就会抛出异常,catch就可以了
driver.findElement(By.partialLinkText("cgy")).click();
第三步就要跳转对应页面,进行数据抓取啦~我就全部写在一起了
/**
* 跳转页面
*
* @param url
* @return
*/
private void skip(String url) {
try {
driver.get(url);
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
close();
}
}
//关闭页面
public void close() {
try {
driver.quit();
} catch (Exception e) {
}
}
//这个方法抓取栏目信息访问量。为了方便就List<Map<String, String>>了。
// head参数是列头及下标,uri就是要抓取页面的地址了~检查分页参数哦
public List<Map<String, String>> getContent(Map<String, Integer> head, String uri) {
//先执行登陆~ 我已经封装了就不粘了~和上面登陆一致。
//login();
//跳转你要抓取的页面数据~
skip(uri);
//下面是针对table渲染的页面~我目前需要的数据只有table的,如果需要其他自行编写即可~
WebElement tbody = driver.findElements(By.tagName("tbody")).get(0);
List<WebElement> tr = tbody.findElements(By.tagName("tr"));
List<Map<String, String>> dataList = new ArrayList<>();
tr.forEach(a -> {
Map<String, String> data = new HashMap<>();
head.forEach((k, v) -> {
WebElement wt = a.findElements(By.tagName("td")).get(v);
data.put(k, wt.getText());
});
dataList.add(data);
});
//关闭 注意我这里没有catch,如果抓取报错会导致页面未关闭
close();
return dataList;
}
第四步数据呈现~
51la会存在流量你懂得~ 建议正则或其他方式过滤。涉及xxx就不粘处理方式了。 建议把数据缓存或处理好入库。频繁调用会登录失败等等问题
效果来个马赛克
当然可以增加查询条件传递参数,拼接对应uri就可以。我感觉太麻烦告诉产品无法实现