通过Jquery遍历Html dom,获取需要的数据。
如果当前的网页不支持Jquery,可以在浏览器强制塞入jquery的引用,从而使用Jquery
var jq = document.createElement('script');
jq.src = 'https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js';
document.getElementsByTagName('head')[0].appendChild(jq);
需求描述
将网站左侧的Tree List 数据按指定的格式导出来
总共有2000个条目,一个个写简直要死人。
两种解决方式:
一种是分析网站加载的内容,分析数据的结构,从而解析出需要的数据;
另外一种,也就是本文推荐的方式,直接使用Jquery分析Dom的结构,按格式输出数据,这是一种更直观和通用的方法;
顺便学习一波Jquery;
直接上代码
$('body ul#toc:first > li > a > span').each(function(i,e){console.log((i+1)+e.innerText);
if($(e).parent().next().length>0)
{
$(e).parent().next().children().each(function(i,e) { console.log(" "+(i+1)+$(e).children().first().text());
if($(e).children().first().next().length>0)
{
$(e).children().first().next().children().each(function(i,e) { console.log(" "+(i+1)+$(e).children().first().text());
if($(e).children().first().next().length>0)
{
$(e).children().first().next().children().each(function(i,e) { console.log(" "+(i+1)+$(e).children().first().text());
})
};
})
};
})
};
})
输出如下:
当然,可以以将父节点的值传递给子节点,从而得到每个节点的全路径。
$('body ul#toc:first > li > a > span').each(function(i,e){console.log((i+1)+e.innerText);
if($(e).parent().next().length>0)
{
$(e).parent().next().children().each(function(i1,e1) { console.log(" "+i+"."+(i1+1)+" "+e.innerText+"/"+$(e1).children().first().text());
if($(e1).children().first().next().length>0)
{
$(e1).children().first().next().children().each(function(i2,e2) { console.log(" "+i+"."+(i1+1)+"."+(i2+1)+" "+e.innerText+"/"+$(e1).children().first().text()+"/"+$(e2).children().first().text());
if($(e2).children().first().next().length>0)
{
$(e2).children().first().next().children().each(function(i3,e3) { console.log(" "+i+"."+(i1+1)+"."+(i2+1)+"."+(i3+1)+" "+e.innerText+"/"+$(e1).children().first().text()+"/"+$(e2).children().first().text()+"/"+$(e3).children().first().text());
})
};
})
};
})
};
})
可以看出,以上的输出似乎已经达到需求了,但是树型表每多一次深度都需要手写一遍重复代码,为了复用代码,可以将相同逻辑写在一个函数中,然后通过递归的方式调用函数本身,这样可以动态地遍历所有层级。
代码如下:
var printTree = function(pi,ps,pe){
pe.children().each(function(i,e){
var vi = (pi==0?"":pi + ".")+(i+1);
var vs = (pi==0?"":ps + "/")+ $(e).children().first().text();
if($(e).children().length>1){
console.group(vi+" "+vs);
printTree(vi,vs,$(e).children().first().next());
console.groupEnd();
}else{
console.log(vi+" "+vs);
}
})
};
printTree(0,"",$('body>ul'))
程序中使用了浏览器提供的函数console,group,可以将结果直接输出成一些手动调整的下拉列表
Jquery的一些语法注意点
:root 获取根元素
:first 获取第一个元素
s1>s2>s3 层级匹配 s2必须是s1的直接孩子节点,s3必须是s2的直接孩子节点
s1 s2 s3 存在性匹配 s2不必是s1的直接孩子节点,s3不必是s2的直接孩子节点
s1,s2,s3 任一匹配 只要包含s1,s2,s3其中一个
$("#xxx").find("span").click() 触发点击事件展开全部列表(不太好用)
前端发展很快,现代浏览器原生 API (querySelector,querySelectorAll)已经足够好用。我们并不需要为了操作 DOM、Event 等再学习一下 jQuery 的 API。同时由于 React、Angular、Vue 等框架的流行,直接操作 DOM 不再是好的模式,jQuery 使用场景大大减少
关于原生API与Jquery操作DOM的对比
可以参考
原生JS替代jQuery的各种方法汇总 - 风雨后见彩虹 - 博客园
以上操作生成的代码不方便管理和固化,可以借助于其他的工具;
在我开发的Roc编辑器中已经将Jquery操作DOM进行了封装
举例如下:
访问网页:
WEB("https://www.yonghongtech.com/help/Z-Suite/9.2/ch/")
获取网页html文本
currentHtml
引用Jquery
CreateJquery
根据ID获取dom元素并输出文本
GetById("ChenPengJquery")
使用Jquery API查找元素
F("#ChenPengJquery")
F("a[href='search.php']")
运行JS代码
点击链接
jq = "$(\"a[href='search.php']\")[0].click()"
Jrun(jq)
向iframe的输入框中输入文本,并点击查询按钮
jq = '$("#hmnavigation").contents().find("input#zoom_searchbox").val("自由式表格");'
jq=jq+'$("#hmnavigation").contents().find("input.zoom_button").click()'
Jrun(jq)
.NET实现的代码
//浏览网页
public static void Navigate(string url)
{
_MutiWebBrowser.cmbAddress.Text = url;
_MutiWebBrowser.Execute( MutiWebBrowser.Command.Go);
}
//获取网页HTML
public static string GetCurrHtml()
{
mshtml.IHTMLDocument2 s = (mshtml.IHTMLDocument2)_MutiWebBrowser.GetDocument();
return s.body.innerHTML;
}
//类似于getElementById
public static string GetById(string id)
{
mshtml.IHTMLDocument2 s = (mshtml.IHTMLDocument2)_MutiWebBrowser.GetDocument();
mshtml.IHTMLElement ele = (mshtml.IHTMLElement)s.all.item(id, 0);
return ele.outerHTML;
}
//引用Jquery
public static void CreateJquery()
{
mshtml.IHTMLDocument2 s = (mshtml.IHTMLDocument2)_MutiWebBrowser.GetDocument();
mshtml.IHTMLElement ele = (mshtml.IHTMLElement)s.all.item("ChenPengJquery", 0);
try
{
if (ele.tagName== "SCRIPT")
{
return;
}
}
catch (Exception)
{
}
string jquerystr = "var jq = document.createElement('script');"
+ "jq.src = 'https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js';"
+ "jq.id = 'ChenPengJquery';"
+ " document.getElementsByTagName('head')[0].appendChild(jq);";
mshtml.IHTMLWindow2 win = (mshtml.IHTMLWindow2)_MutiWebBrowser.GetDocument().parentWindow;
win.execScript(jquerystr, "Javascript");
}
//运行Js代码
public static void JRUN(string jscode)
{
mshtml.IHTMLWindow2 win = (mshtml.IHTMLWindow2)_MutiWebBrowser.GetDocument().parentWindow;
win.execScript(jscode, "Javascript");
}
//调用Jquery API访问元素
public static string getElemetByJquery(string mode)
{
char r = mode.FirstOrDefault(t => t == '\'' || t == '"');
r = (r == '"')? '\'':'"';
string jquerystr = $"var v = $({r}{mode}{r});\r\n"
+ "var str = '';\r\n"
+ "v.each(function(){str+=this.outerHTML+'\\r\\n';});\r\n"
//+ "$('a').each(function(){str+=this.getAttribute('href')+'\\r\\n';});\r\n"
+ "$('#ChenPengJquery').attr('cp',encodeURI(str));";
mshtml.IHTMLWindow2 win = (mshtml.IHTMLWindow2)_MutiWebBrowser.GetDocument().parentWindow;
win.execScript(jquerystr, "Javascript");
mshtml.IHTMLDocument2 s = (mshtml.IHTMLDocument2)_MutiWebBrowser.GetDocument();
mshtml.IHTMLElement ele = (mshtml.IHTMLElement)s.all.item("ChenPengJquery", 0);
return (string)ele.getAttribute("cp");
}
//类似于getElementByTagName
public static string GetAllTags(string tagName)
{
mshtml.IHTMLDocument2 s = (mshtml.IHTMLDocument2)_MutiWebBrowser.GetDocument();
mshtml.IHTMLElementCollection eles = (mshtml.IHTMLElementCollection)s.all.tags(tagName);
string result = "";
for (int i = 0; i < eles.length; i++)
{
result += ((mshtml.IHTMLElement)eles.item(i)).innerHTML+"\r\n";
}
return result;
}
谷歌浏览器最新版本已经把录制回放用户操作功能内置在开发者页面中
录制回放操作
可以对录制的记录进行可视化编辑,导出JS代码
可以在很大程度上节省许多无脑操作
![](https://img-blog.csdnimg.cn/c42a921b9d7f4678b2fde1f9210b21ac.png)