需求:爬取项目中指定url页面,获取js执行后的html页面;
调整样式,将此html页面(需支持highchart图表,表格,表单等),通过邮件方式发送给用户查看.
共有问题:获取form表单中的值,
爬取输入框中的内容,
获取 input里面value的值。
问题产生原因:爬虫爬取结果为html页面的"字符串"(相当于直接复制浏览器窗口里html标签的文本内容),
而input标签的value值在字符串中不可见,需通过节点操作(input.value)拿到
解决思路:修改html字符串所有input等输入框标签,给标签字符串添加value=“真实值”(<input type="text" value="真实值">)
ps:我的需求爬取的是自己的前台vue项目,让前台生成form表单时所有值都写在placeholder里面(?因为value属性加不了);也可以获取后台通过BY.xpath语法,获取所有的输入框节点,通过节点操作给input框字符串,添加属性值value='实际值‘
测试1:基于java嵌套浏览器:JBrowserDriver
package test.mail.demo;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import com.machinepublishers.jbrowserdriver.JBrowserDriver;
import com.machinepublishers.jbrowserdriver.Settings;
import com.machinepublishers.jbrowserdriver.Timezone;
public class JBrowserDemoTest {
/*
* 采纳原因1:满足需求;
* 采纳原因2:代码量少;java嵌套浏览器,项目移植方便;
*
*/
public static void main(String[] args) throws IOException {
String loginUrl="https://panjiachen.gitee.io/vue-element-admin/#/login?redirect=%2Fdashboard";
String url="https://panjiachen.gitee.io/vue-element-admin/#/permission/role";
String htmlStr = getUrlHtml(loginUrl,url);
System.out.println("html"+htmlStr);
//将解析url的html内容文件形式写到当前项目下,方便浏览器打开对比页面爬取效果
FileUtils.writeStringToFile(new File("url内容.html"), htmlStr,"UTF-8");
}
//方案1,获取js执行后的页面:JBrowserDriver
public static String getUrlHtml(String loginUrl,String url) {
JBrowserDriver webDriver = new JBrowserDriver(Settings.builder().
timezone(Timezone.AMERICA_NEWYORK).build());
//模拟登入
//方法1: webDriver.get(null); webDriver.manage().addCookie(cookie);
//方法2:
webDriver.get(loginUrl);
WebElement username = webDriver.findElement(By.xpath("//*[@name=\"username\"]"));
WebElement pwd = webDriver.findElement(By.xpath("//*[@name=\"password\"]"));
username.clear();
username.sendKeys("admin");
pwd.clear();
pwd.sendKeys("11111111");
webDriver.findElement(By.xpath("//*[@class=\"el-button el-button--primary el-button--medium\"]")).click();
//此时已经携带cookie,可访问授权页面
webDriver.get(url);
//输出js执行后的html
String htmlStr = webDriver.getPageSource();
webDriver.quit();
return htmlStr;
}
//参考地址:
// 基于WebKit 无图形化浏览器 jBrowserDriver:https://www.oschina.net/p/jbrowserdriver
// API文档:http://machinepublishers.github.io/jBrowserDriver/
// jBrowserDriver是一个纯Java编写的可编程、嵌入式的,浏览器驱动,基于WebKit:https://java.ctolib.com/jbrowserdriver.html
/*pom依赖,(我的项目是局域网,在联网电脑,新建项目把依赖jar全部拷贝)
<dependency>
<groupId>com.machinepublishers</groupId>
<artifactId>jbrowserdriver</artifactId>
<version>1.1.1</version>
</dependency>
*/
}
测试2.基于谷歌无头浏览器:selenium+chromedriver+chrome headless(谷歌无头浏览器,windows谷歌浏览器就行)
package test.mail.demo;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class ChromeHeadlessDemoTest {
/*
* 不采用原因1:我的项目环境是Linux环境,局域网,无法联网下载谷歌无头浏览器;本地环境依赖太多;
* 不采用原因2:需求只需要爬取指定url页面,不需要进一步爬取页面中的链接,此选择过于笨重;换环境麻烦;
* chromedriver_linux64
* google-chrome-stable_current_x86_64.rpm
* https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm
*/
public static void main(String[] args) throws IOException {
String loginUrl="https://panjiachen.gitee.io/vue-element-admin/#/login?redirect=%2Fdashboard";
String url="https://panjiachen.gitee.io/vue-element-admin/#/permission/role";
String htmlStr = getUrlHtml(loginUrl,url);
System.out.println("html"+htmlStr);
//将解析url的html内容文件形式写到当前项目下,方便浏览器打开对比页面爬取效果
FileUtils.writeStringToFile(new File("url内容.html"), htmlStr,"UTF-8");
}
//方案2,获取js执行后的页面:selenium+chromedriver+chrome headless(谷歌无头浏览器,windows谷歌浏览器就行)
public static String getUrlHtml(String loginUrl,String url) {
//准备工作:下载你使用的谷歌浏览器对应版本的chromedriver;地址 https://npm.taobao.org/mirrors/chromedriver/
//前提:将chromedriver。exe放到你的谷歌浏览器安装目录(与chrome.exe平级)
System.setProperty("webdriver.chrome.driver","C:\\Program Files (x86)\\Google\\Chrome\\Application\\chromedriver.exe");
WebDriver webDriver = new ChromeDriver();
//模拟登入
//方法1: webDriver.get(null); webDriver.manage().addCookie(cookie);
//方法2:
webDriver.get(loginUrl);
WebElement username = webDriver.findElement(By.xpath("//*[@name=\"username\"]"));
WebElement pwd = webDriver.findElement(By.xpath("//*[@name=\"password\"]"));
username.clear();
username.sendKeys("admin");
pwd.clear();
pwd.sendKeys("11111111");
webDriver.findElement(By.xpath("//*[@class=\"el-button el-button--primary el-button--medium\"]")).click();
//此时已经携带cookie,可访问授权页面
webDriver.get(url);
//等待1s;
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
//输出js执行后的html
String htmlStr = webDriver.getPageSource();
webDriver.quit();
return htmlStr;
}
//参考地址:
// java 利用selenium+chromedriver实现爬虫:https://www.jianshu.com/p/30b60f5da23c
//selenium+Chromedriver模拟登陆操作: https://www.jianshu.com/p/308daa2b91c2
/*
*pom依赖
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
*/
//linux相关,依赖太多,最终放弃离线安装
//linux局域网安装chrome缺少依赖libappindicator3.so.1及liberation-fonts:https://blog.csdn.net/wangying202/article/details/102565367
//linuxrpm包下载地址:http://rpmfind.net/
// http://rpmfind.net/linux/centos/7.7.1908/os/x86_64/Packages/liberation-fonts-1.07.2-16.el7.noarch.rpm
}
测试3:java嵌套浏览器:htmlunit
package test.mail.demo;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
public class HtmlUnitDemoTest {
/*
* 不采用原因1:爬取highchart图失败(svg中with,height:NaN),
* 不采用原因2:爬取我们前台vue项目页面的表单,样式margin-left生成不对;
*
*/
public static void main(String[] args) throws IOException {
String loginUrl="https://panjiachen.gitee.io/vue-element-admin/#/login?redirect=%2Fdashboard";
String url="https://panjiachen.gitee.io/vue-element-admin/#/permission/role";
String htmlStr = getUrlHtml(loginUrl,url);
System.out.println("html"+htmlStr);
//将解析url的html内容文件形式写到当前项目下,方便浏览器打开对比页面爬取效果
FileUtils.writeStringToFile(new File("url内容.html"), htmlStr,"UTF-8");
}
//方案3,获取js执行后的页面:htmlunit
public static String getUrlHtml(String loginUrl,String url) throws IOException {
WebClient client=new WebClient(BrowserVersion.CHROME);//设置浏览器内核
client.getCookieManager().setCookiesEnabled(true);//设置cookie是否可用
client.getOptions().setJavaScriptEnabled(true); // js是否可用
client.getOptions().setCssEnabled(true); //css ,vue项目需设置为true,jq项目一般设置false因为影响运行速度
client.getOptions().setThrowExceptionOnScriptError(false);
client.getOptions().setThrowExceptionOnFailingStatusCode(false);
client.setAjaxController(new NicelyResynchronizingAjaxController()); // ajax设置
//没有写登入
HtmlPage page = client.getPage(url);
String htmlStr=page.asXml();
//关闭
client.close();
return htmlStr;
}
//参考地址:
// 使用htmlunit工具来实现对新浪的模拟登录获取cookie操作:https://blog.csdn.net/m0_37300802/article/details/79046034
//
/*
* pom依赖
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.38.0</version>
</dependency>
*/
}
测试4:PhantomJS
package test.mail.demo;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
public class PhantomJSDemoTest {
/*
* 不采用原因1:爬取highchart图失败(svg中with,height:NaN),爬取我们前台vue项目失败率高;
* 不采用原因2:我的项目环境是Linux环境,局域网,无法联网下载linux版PhantomJS;本地环境依赖太多;
* 不采用原因3:需求只需要爬取指定url页面,不需要进一步爬取页面中的链接,此选择过于笨重;换环境麻烦;
* phantomjs.exe
*/
public static void main(String[] args) throws IOException {
String loginUrl="https://panjiachen.gitee.io/vue-element-admin/#/login?redirect=%2Fdashboard";
String url="https://panjiachen.gitee.io/vue-element-admin/#/permission/role";
String htmlStr = getUrlHtml(loginUrl,url);
System.out.println("html"+htmlStr);
//将解析url的html内容文件形式写到当前项目下,方便浏览器打开对比页面爬取效果
FileUtils.writeStringToFile(new File("url内容.html"), htmlStr,"UTF-8");
}
//方案3,获取js执行后的页面:PhantomJS
public static String getUrlHtml(String loginUrl,String url) throws IOException {
//准备工作:下载phantomjs.exe:https://npm.taobao.org/mirrors/phantomJS/
String exePath="E:\\phantomjs-windows\\bin\\phantomjs.exe";
Runtime rt = Runtime.getRuntime();
//登入,cookie写入文件(默认当前目录)
String cookieJsPath="E:\\phantomjs-windows\\bin\\writeCookie.js";
Process loginP = rt.exec(exePath + " " + cookieJsPath + " " + loginUrl);
loginP.destroy();
//读取文件cookie,访问授权页面
String htmlJsPath="E:\\phantomjs-windows\\bin\\getHtml.js";
Process p = rt.exec(exePath + " " + htmlJsPath + " "+ url);
InputStream is = p.getInputStream();
//is流为 js中cosole。log内容,
String htmlStr = IOUtils.toString(is, "utf-8");
return htmlStr;
}
//参考地址:
//phantomjs使用说明:https://www.cnblogs.com/Sonet-life/p/5393730.html
//java使用phantomJs抓取动态页面:https://blog.csdn.net/kaka0930/article/details/68941932
//Java实现HighCharts纯后台图表生成:https://blog.csdn.net/MAOZEXIJR/article/details/84886104
}