环境:windows 11 ; Qt 5.15;测试浏览器 edge;
功能描述:
通过从浏览器地址栏复制 URL 网址后,获取浏览器同时写到剪贴板中的对应网页标题。
注:从别的地方复制的纯文本url,剪贴板是没有对应的附加信息的。如果要获取标题是需要借助Qt的web相关的类,加载网页并解析来获取,不是本文描述的方式。
代码示例:
//依赖头文件:
#include <QApplication>
#include <QClipboard>
#include <QMimeData>
#include <QJsonDocument>
#include <QDebug>
//实现代码段:
QClipboard *clipboard = QApplication::clipboard();
//剪贴板的文本部分
QString urlStr = clipboard->text();
//附带的MimeData
const QMimeData *const data = clipboard->mimeData();
if (!data) return ;
//Mimedata里是几个键值对,下面获取的就是标题相关的json
const QByteArray rawData = data->data(QLatin1String("application/x-qt-windows-mime;value=\"Link Preview Format\""));
//字符编码的转换,目前这块也没有搞得很明白。直接搞成json解析的话,拿不到属性值,有时间再探究下。
QString jsonStr = QString::fromUtf8(rawData);
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonStr.toUtf8());
// 获取网页标题
QString title = jsonDoc["title"].toString();
qDebug() << "Title: " << title;
探索过程:
这里是对功能实现过程的记录,不感兴趣的可以不看。
使用vscode等类型的markdown编辑器时,发现从浏览器地址栏复制的网页链接在粘贴时,直接变成了以对应 网页标题为文本 的 超链接。
开始猜想的是就是通过网页url去加载下网页,然后解析html拿到title字段。包括以关键词: “Qt 获取网页标题” 这样搜索,都是这种猜想的解决方式。
但是通过断网,抓网络包,以及观察到编辑器软件在粘贴时是即时转换的,所以可以判定有跟简单直接的方式。
结合经验,剪贴板是有附加信息部分的,这个标题应该是从附加信息里拿到的。现在的问题是两个:1.怎样才能拿到,通过了解 QClipboard 这个类,可以完成对剪贴板的各种操作。
2.从哪里拿到,也就是附加信息放在了哪里。
关于第二个问题,偶然从参考文章【1】里了解到:
在地址栏复制时,Chrome 浏览器往剪贴板塞了一个 “text/link-preview” 类型的数据
尝试直接使用这个key进行获取,但是并不能拿到,只得去翻看 QClipboard.cpp 的源码,发现
QString QClipboard::text(QString &subtype, Mode mode) const
{
const QMimeData *const data = mimeData(mode);
if (!data)
return QString();
//通过下面这句,可以拿到所有的属性key,打印出来,可以发现Qt的把我们需要的属性名称换了。
//实例代码里对应使用被替换后的属性名称即可
const QStringList formats = data->formats();
if (subtype.isEmpty()) {
if (formats.contains(QLatin1String("text/plain")))
subtype = QLatin1String("plain");
else {
for (int i = 0; i < formats.size(); ++i)
if (formats.at(i).startsWith(QLatin1String("text/"))) {
subtype = formats.at(i).mid(5);
break;
}
if (subtype.isEmpty())
return QString();
}
} else if (!formats.contains(QLatin1String("text/") + subtype)) {
return QString();
}
const QByteArray rawData = data->data(QLatin1String("text/") + subtype);
auto encoding = QStringConverter::encodingForData(rawData);
if (!encoding)
encoding = QStringConverter::Utf8;
return QStringDecoder(*encoding).decode(rawData);
}
参考文章
【1】如何获取链接标题?