爬取URL解析JS后页面,简单例子:ChromeDriver,htmlunit,jbrowserdriver,phantomjs

昝欣可
2023-12-01

需求:爬取项目中指定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
}

 

 类似资料: