如果你不需要在linux docker 上运行爬虫,就不需要看这篇文档了,直接拉到最下面点击第二个 参考文档 即可。
问:selenium+WebDriver+chrome 是如何实现爬虫的或者自动化测试的。
答:selenium WebDriver 可以模拟页面上的操作,仿佛一个测试人员 正在拿着鼠标在页面上点来点去。并且可以获取页面上的元素,元素的属性值。
创建一个WebDriver对象,就是打开一个会话。
第一步:拉取镜像
1.拉取镜像
1.1官方镜像
sudo docker run -d -p 4444:4444 --shm-size=2g selenium/standalone-chrome
1.2这个官方镜像是国外的,拉取不下来,使用阿里云加速器
使用阿里云加速器其实要的就是红框3中的json,赋值红框3中的json,复制红框2中的地址,替换掉json里面的链接,得到新的json。(这个链接每个人都不一样)
{
"registry-mirrors": ["https://********"]
}
然后把这个json保存到 你linux机器上 /etc/docker/daemon.json 这个文件里,没有的话就创建这个文件。
完事之后,再次执行上面的命令就可以成功了
运行成功之后,查看容器,会看到已经容器已经运行了。
sudo docker ps
在你的电脑,不是linux,访问以下地址
http://<你的linux的ip地址>:4444/
如果可以看到下面的页面,就说明容器运行成功
sessions:代表创建了几个会话。
max.concurrentcy: 代表 你这个容器同时可以处理几个对话。
图中这种情况只能 同时模拟一个网页,也就是同时只能处理一个会话。
代码部分
依赖
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
WebDriver chromeDriver = new RemoteWebDriver(new URL("http://<linux ip 地址>:4444/wd/hub"), DesiredCapabilities.chrome());
这段代码就是创建和你linux机器上 chrome 容器服务的 会话。
可以本地写个main方法运行一下这段代码。但是一定要加上下面的代码,关闭会话。
chromeDriver.quit();
为了看到效果,可以睡个5秒钟。不报错就说明成功了,同时 http://<你的linux的ip地址>:4444/ 这个地址上,sessions 的值应该变成1,5秒之后变成0。
注意:如果你心急没有加上 关闭会话 的代码就着急运行了。那么你就只能去linux上重启 容器了。
package com.water.disasters.service.schedule;
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.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.net.URL;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.openqa.selenium.support.ui.ExpectedConditions.numberOfWindowsToBe;
import static org.openqa.selenium.support.ui.ExpectedConditions.titleIs;
public class MainClass {
public static void main(String[] args) {
WebDriver driver = null;
try {
//打开一个浏览器窗口
//加载 chromedriver 驱动
driver = new RemoteWebDriver(new URL("http://192.168.183.120:4444/wd/hub"), DesiredCapabilities.chrome());
//打开百度链接
driver.navigate().to("http://www.baidu.com/");
//在搜索文本框输入"csdn 西凉的悲伤"
driver.findElement(By.id("kw")).sendKeys("csdn 西凉的悲伤");
//点击搜索按钮
driver.findElement(By.id("su")).click();
//存储当前原始窗口或页签的ID
String originalWindow = driver.getWindowHandle();
//获取当前打开的窗口或页签数
int windosSize = driver.getWindowHandles().size();
//等到百度搜索结果页面元素加载完(这里最多等5秒)
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
//点击第一条搜索结果,会打开新页签,也就是第2个页签
driver.findElement(By.xpath("//*[@id='content_left']/div[@id='1']/div[@class='c-container']/div/h3/a")).click();
WebDriverWait wait = new WebDriverWait(driver, 10);
//这里不我建议用,因为我打开第二窗口打不开,可能是因为分配的资源大小的问题。我实际处理业务都是 单窗口操作的,先把第二个网页的链接保存到数据库
//等待第2个新窗口或新页签打开
wait.until(numberOfWindowsToBe(2));
//循环指导找到新窗口或页签的句柄
for (String windowHandle : driver.getWindowHandles()) {
if (!originalWindow.contentEquals(windowHandle)) {
//driver切换为新窗口或新页签的
driver.switchTo().window(windowHandle);
break;
}
}
//等待新窗口或新页签的内容加载
wait.until(titleIs("西凉的悲伤的博客_CSDN博客-java,工具,其他领域博主"));
//读取当前页面标题
System.out.println("当前网址的标题:" + driver.getTitle());
//从地址栏中读取当前 URL
System.out.println("当前网址的链接:" + driver.getCurrentUrl());
System.out.println();
//获取多个 h4 标签元素
List<WebElement> articleTitles = driver.findElements(By.xpath("//*[@class='blog-list-box-top']/h4"));
//获取多个 a 标签元素
List<WebElement> articleUrls = driver.findElements(By.xpath("//*[@class='blog-list-box']/a"));
for (int i = 0; i < articleTitles.size(); i++) {
//获取 h4 标签中的显示文本
String articleTitle = articleTitles.get(i).getText();
//获取 a 标签里的 href 属性的值
String articleUrl = articleUrls.get(i).getAttribute("href");
System.out.println("文章标题:" + articleTitle + " 链接:" + articleUrl);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
driver.quit();
}
}
}
只是一个例子,selenium+java 操作的语法,大家去网上搜搜吧,我就不赘述了。
但是搜的时候要注意 windows 上 和 docker 容器上 创建会话的方式不一样,即创建Webdriver 的方式不一样。