htmkl官网 : https://htmlunit.sourceforge.io/ (本次用的为HtmlUnit 2.51 )
这是小编第一次记录自己的博客,如果不对的地方请留言指正,感谢!🤞
近期公司网站的的 meta title 需要更换了,给了一个excl,600多行,我自己懒得搞,于是就想着可以不可用网站自动化测试,让代码帮我点,于是有了这次,闲言少叙,上代码!
- 代码主体
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.*;
import com.gargoylesoftware.htmlunit.util.Cookie;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;
import org.apache.commons.io.input.BufferedFileChannelInputStream;
import sun.jvm.hotspot.code.Location;
import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Httpunit自动化 {
public static void main(String[] args) throws IOException, BiffException {
//获取表格的所有数据
Map<String, String> domian_list = getDomains();
//设置网址
String pageUrl = "这里是你需要爬取的网页";
//创建一个webclient
//-- 127.0.0.1/8001/http,是以127.0.0.1的8001端口用http的方式启用本地代理
WebClient webClient = new WebClient(BrowserVersion.CHROME,"127.0.0.1",8001,"http");
//参数设置
//启动JS
webClient.getOptions().setJavaScriptEnabled(true);
//禁用CSS,可避免自动二次请求css进行渲染
webClient.getOptions().setCssEnabled(false);
//启动客户端重定向
webClient.getOptions().setRedirectEnabled(true);
//运行错误时,是否抛出异常
webClient.getOptions().setThrowExceptionOnScriptError(false);
//禁用日志打印
Logger.getLogger("com.gargoylesoftware").setLevel(Level.OFF);
//设置超时
webClient.getOptions().setTimeout(10000);
//忽略证书
webClient.getOptions().setUseInsecureSSL(true);
//设置Ajax
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
//设置cookie
webClient.getCookieManager().setCookiesEnabled(true);
//获取页面
HtmlPage loginPage = webClient.getPage(pageUrl + "signin.html");
// 根据form的名字获取页面表单,也可以通过索引来获取:loginPage.getForms().get(0)
HtmlForm form = loginPage.getForms().get(0);
//获取姓名输入框
HtmlTextInput username = form.getInputByName("u");
//获取密码输入框
HtmlPasswordInput userPass = form.getInputByName("p");
//获取谷歌身份码
HtmlTextInput googleCode = form.getInputByName("g");
//设置用户和密码
username.setValueAttribute("用户名");
userPass.setValueAttribute("密码");
//等待输入谷歌验证码
System.out.print("请输入谷歌验证码: ");
Scanner input = new Scanner(System.in);
String code = input.nextLine();
input.close();
//设置谷歌验证码
googleCode.setValueAttribute(code);
//获取提交按钮
HtmlInput button = form.getInputByName("signin");
HtmlPage indexPage = button.click();
//等待JS驱动dom完成后获得还原后的网页
webClient.waitForBackgroundJavaScript(10000);
if (indexPage.getTitleText().equals("Admin/Summary") || indexPage.getTitleText().equals("Admin Settings")) {
System.out.println("登陆成功!");
}else{
System.out.println(indexPage.asXml());
//关闭webclient
webClient.close();
System.out.println("登陆失败,关闭程序!");
return;
}
int pas = 1;
for (String tdl : domian_list.keySet()) {
if(pas < 9) {
pas++;
continue;
}
//登陆后直接跳转路由至 Tlds 页面
HtmlPage TldsPage = webClient.getPage(pageUrl + "****.html");
webClient.waitForBackgroundJavaScript(10000);
System.out.println("开始第" + pas + "次自动操作!");
System.out.println("进入" + TldsPage.getTitleText() + "页面!");
//精准定位域名后缀列表
List<HtmlAnchor> domains = TldsPage.getByXPath("//tr//td[1]//a");
int countA = getCountForA(domains, tdl);
if (countA != -1) {
System.out.println("找到匹配项 : ==> ");
System.out.println(domains.get(countA).getHrefAttribute());
HtmlPage tldsinfo = domains.get(countA).click();
webClient.waitForBackgroundJavaScript(10000);
System.out.println("进入" + tldsinfo.getTitleText() + "页面!");
HtmlTableCell htmlTd = (HtmlTableCell) tldsinfo.getByXPath("//form[1]//tr[1]//td[2]").get(0);
String msg = "." + htmlTd.getTextContent().toLowerCase().trim();
if (msg.contains(tdl)) {
System.out.println("匹配到了 :" + msg + "==>" + tdl);
HtmlForm tld_inf_form = tldsinfo.getForms().get(1);
HtmlTextInput title = tld_inf_form.getInputByName("title");
System.out.println(title.getValueAttribute() + " ==> " + domian_list.get(tdl));
title.setValueAttribute(domian_list.get(tdl));
HtmlInput save = tld_inf_form.getInputByValue("Save Tld Info");
save.click();
webClient.waitForBackgroundJavaScript(10000);
System.out.println("修改完成,返回域名列表!");
BufferedWriter file = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("domain_log.txt",true), "utf-8"));
file.write("操作次数:" + pas +" 操作域名后缀:" + tdl);
file.newLine();
file.close();
}
if(tdl.equals(".yachts")){
webClient.close();
System.out.println("第一阶段任务完成,关闭程序!");
return;
}
} else {
System.out.println("未找到匹配域名:" + tdl);
BufferedWriter file = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("log.txt",true), "utf-8"));
file.write(tdl);
file.newLine();
file.close();
System.out.println("未找到域名已经列入缺省列表中!");
continue;
}
pas++;
}
//关闭webclient
webClient.close();
System.out.println("关闭程序!");
}
- Excel 表格读取函数。-- getDomains()
static private Map<String, String> getDomains() throws IOException, BiffException {
File domains = new File("/Users/Shared/Hugh/work/autoWeb/src/Dynadot Meta Title Restructure List_Sept2021.xls");
//检验文件是否存在
if(!domains.exists()){
System.out.println(domains.getName() + "不存在!");
return null;
}else {
System.out.println("正在读取EXCL表格!");
}
Workbook workbook = Workbook.getWorkbook(domains);
Sheet sheet= workbook.getSheet(0);
Cell cell = sheet.getCell(0,0);
Cell content ;
System.out.println(cell);
Map<String,String> listCell = new LinkedHashMap<>();
for (int i = 2 ;i < 520;i++){
cell = sheet.getCell(0,i);
content = sheet.getCell(1,i);
String dtl = content.getContents();
if(dtl.indexOf("Domains") > 0){
dtl = dtl.substring(0,dtl.indexOf("Domains")).trim().toLowerCase();
}else if(dtl.indexOf("Domain") > 0){
dtl = dtl.substring(0,dtl.indexOf("Domain")).trim().toLowerCase();
}
listCell.put(dtl,content.getContents());
}
workbook.close();
System.out.println("表格数据读取完毕!");
return listCell;
}
- 列表内容比对函数 -- getCountForA(List<HtmlAnchor> domains,String tdl)
static private int getCountForA(List<HtmlAnchor> domains,String tdl) {
int msg =-1;
for (int i = 0; i < domains.size(); i++) {
String tdls = domains.get(i).getTextContent();
if (tdls.equals(tdl.trim())) {
System.out.println("The domain name :" + domains.get(i).getTextContent());
System.out.println("The tdl is :" + tdl);
System.out.println("The result is true!");
msg = i;
break;
}
}
return msg;
}
因为本人比较懒,只是为了快速的将工作做完,所以这个代码还有很大的优化空间,比如:
- 断线重连
- 比如说配合Swing做成可视化的插件或者程序。
- 将网页内容部分变成可输入的变量等等。
说一下个人对HtmlUnit的理解吧
- HtmlUnit和Jsoup
Jsoup:
jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
HtmlUnit:
它可以简单的理解为是一个嵌入式没有界面的浏览器。
HtmlUnit相对于Jsoup最大的不同之处大概就是,Jsoup一般只用于静态网站的爬取,而HtmlUnit则是被用来进行网页自动化测试的,基于这些特点,仅仅考虑静态网站的角度下,二者从运行速度上来说,Jsoup还是好点的。但是涉及到网页复杂操作就不行了。
第一次写博客,因为本人对HtmIunit的理解仅仅体现在上述代码,就不过多的板门弄斧了,也希望以后可以给大家提供更多干货,一起加油!