admin管理员组

文章数量:1568424

1.需求:产品需要嵌入某路由器控制界面,但是想隐藏路由器的品牌信息。

先看看效果图:

JS注入前:

 JS注入后

2.C++代码,请看代码注释:


#include <QApplication>
#include <QWebEngineView>
#include <QPushButton>
#include <QTimer>
#include <QFile>
#include <QWebEngineScript>
#include <QIODevice>
#include <QWebEngineProfile>
#include <QWebEngineScriptCollection>
#include <QWebEngineSettings>
#include <QWebEngineCookieStore>

QUrl commandLineUrlArgument()
{
	const QStringList args = QCoreApplication::arguments();
	for (const QString& arg : args.mid(1)) {
		if (!arg.startsWith(QLatin1Char('-')))
			return QUrl::fromUserInput(arg);
	}
	return QUrl(QStringLiteral("http://tplogin/login.htm"));
}

int main(int argc, char* argv[])
{
	QCoreApplication::setOrganizationName("QtExamples");
	QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
	QApplication app(argc, argv);

	qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "7777");	// 设置远程调试环境变量
	QWebEngineView view;
	view.setUrl(commandLineUrlArgument());

	QWebEngineProfile* engineProfile = view.page()->profile();
	engineProfile->clearHttpCache();        // 清理缓存
	engineProfile->clearAllVisitedLinks();  // 清理浏览记录
	engineProfile->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies);// 会话和持久性cookie都存储在内存中 
	engineProfile->setHttpCacheType(QWebEngineProfile::NoCache);// 禁用内存和磁盘缓存。

	QWebEngineCookieStore* pCookie = engineProfile->cookieStore();
	pCookie->deleteAllCookies();            // 清理cookie
	pCookie->deleteSessionCookies();        // 清理会话cookie

	// 在DocumentReady的时候注入js代码
	QFile file("test.js");
	if (file.open(QIODevice::ReadOnly))
	{
		QString content = file.readAll();
		file.close();
		QWebEngineScript script;
		script.setSourceCode(content);
		script.setWorldId(QWebEngineScript::MainWorld);
		script.setInjectionPoint(QWebEngineScript::DocumentReady);
		view.page()->profile()->scripts()->insert(script);
	}
	
	// QWebEngineView开始加载的时候
	QObject::connect(&view, &QWebEngineView::loadStarted, [&view] {
		qDebug() << "loadStarted";
	});

	// QWebEngineView加载完成的时候
	QObject::connect(&view, &QWebEngineView::loadFinished, [&view] {
		// 注意此处需要延时再执行js操作,否则获取不到文档对象。
		QTimer::singleShot(500, [&view] {
			qDebug() << "loadFinished" << view.title();
			view.page()->runJavaScript("$('#menu-advanced-running-status-li a').click()");
			view.show();
		});
	});

	view.resize(1024, 750);
	view.show();

	return app.exec();
}

3.test.js代码

// test.js
// 获取head标签,插入style标签,此处css的作用是隐藏界面上的一系列元素
var head = document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
head.appendChild(style);
var css = "\
    body > div.login-banner > a {display: none;}\r\n\
    body > div.login-banner > h1 {padding-left: 156px;}\r\n\
    body > div.top-banner {display: none;}\r\n\
    body > div.user-info {display: none;}\r\n\
    body > div.top-tip {display: none;}\r\n\
    #menu-advanced-homepage-li  {display: none;}\r\n\
    #func-advanced > div.home-page-main > div.wireless-info {display: none;}\r\n\
    #func-advanced > div.home-page-main > div.system-topo-info > div.system_info_panel > div.content > div:nth-child(4) {display: none;}\r\n\
    #menu-advanced-ap-manager-li {display: none;}\r\n\
    #menu-advanced-mesh-manage-li {display: none;}\r\n\
    #menu-advanced-advanced-li > div > ul > li:nth-child(5) {display: none;}\r\n\
    #menu-advanced-sys-tools-li > div > ul > li.sec.sec-fst {display: none;}\r\n\
    #menu-advanced-sys-tools-li > div > ul > li:nth-child(6) {display: none;}\r\n\
    #menu-wizard  {display: none;}\r\n\
    #menu-footer  {display: none;}\r\n\
";
style.innerHTML = css;

4.注意QWebEngineView::loadFinished信号后延时了500ms再去执行js,否则获取不到文档对象。此处有个较为优雅的处理方法,就是在注入的js中再调用C++的方法,我的其它项目这样做过。

本文标签: 网页QWebEngineViewjscssJavaScript