应用场景
1. 档案管理
在企业或机构的档案管理中,常常会有大量的 PDF 格式的文件,如合同、报告、发票等。这些文件的原始文件名可能没有明确的标识,不利于查找和管理。通过批量获取 PDF 局部文字内容并改名,可以根据文件中的关键信息(如合同编号、报告标题等)为文件重新命名,提高档案管理的效率。
2. 学术资料整理
在学术研究中,会收集大量的学术论文、研究报告等 PDF 文件。这些文件的文件名可能是随机生成的或者不具有明确的主题信息。使用本方案可以提取 PDF 中的标题、作者等关键信息,为文件重新命名,方便学者对学术资料进行分类和检索。
实现方案概述
本方案将使用 QT 构建图形用户界面,结合百度云 OCR API 实现批量获取 PDF 局部文字内容并对文件进行改名的功能。主要步骤包括:使用 QT 选择 PDF 文件目录,将 PDF 转换为图片(因为百度云 OCR 主要处理图片),指定局部区域进行 OCR 识别,获取识别结果作为新文件名,最后对 PDF 文件进行重命名。
准备工作
- 注册百度云账号:在百度云官网注册账号并创建 OCR 应用,获取 API Key 和 Secret Key。
- 安装 QT:确保已经安装了 QT 开发环境。
- 安装依赖库:需要安装
Poppler
用于 PDF 转图片,以及QNetworkAccessManager
用于网络请求。
代码实现
1. 创建 QT 项目
创建一个新的 QT Widgets Application 项目。
2. 界面设计
在 mainwindow.ui
中设计简单的界面,包含一个按钮用于选择 PDF 文件目录,一个文本框用于显示操作结果。
3. 代码实现
cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QDir>
#include <QProcess>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QImage>
#include <QPixmap>
#include <QPainter>
#include <poppler/qt5/poppler-qt5.h>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->selectDirButton, &QPushButton::clicked, this, &MainWindow::selectDirectory);
networkManager = new QNetworkAccessManager(this);
connect(networkManager, &QNetworkAccessManager::finished, this, &MainWindow::onNetworkReplyFinished);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::selectDirectory()
{
QString dir = QFileDialog::getExistingDirectory(this, tr("Select Directory"), "", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (!dir.isEmpty()) {
QDir directory(dir);
QStringList filters;
filters << "*.pdf";
QStringList pdfFiles = directory.entryList(filters, QDir::Files);
for (const QString &pdfFile : pdfFiles) {
QString pdfPath = directory.filePath(pdfFile);
processPDF(pdfPath);
}
}
}
void MainWindow::processPDF(const QString &pdfPath)
{
Poppler::Document *document = Poppler::Document::load(pdfPath);
if (!document || document->isLocked()) {
ui->resultTextEdit->append("Failed to load PDF: " + pdfPath);
delete document;
return;
}
Poppler::Page *page = document->page(0);
if (!page) {
ui->resultTextEdit->append("Failed to get page from PDF: " + pdfPath);
delete document;
return;
}
QImage image = page->renderToImage();
// 假设我们要提取的局部区域(这里需要根据实际情况调整)
QRect region(100, 100, 200, 50);
QImage croppedImage = image.copy(region);
QByteArray imageData;
QBuffer buffer(&imageData);
buffer.open(QIODevice::WriteOnly);
croppedImage.save(&buffer, "JPEG");
buffer.close();
QString apiKey = "your_api_key";
QString secretKey = "your_secret_key";
QString tokenUrl = QString("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%1&client_secret=%2").arg(apiKey).arg(secretKey);
QNetworkRequest tokenRequest(QUrl(tokenUrl));
networkManager->get(tokenRequest);
pdfPaths.append(pdfPath);
imageDatas.append(imageData);
delete page;
delete document;
}
void MainWindow::onNetworkReplyFinished(QNetworkReply *reply)
{
if (reply->error() == QNetworkReply::NoError) {
QByteArray responseData = reply->readAll();
QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData);
QJsonObject jsonObj = jsonDoc.object();
if (jsonObj.contains("access_token")) {
QString accessToken = jsonObj["access_token"].toString();
if (!pdfPaths.isEmpty() && !imageDatas.isEmpty()) {
QString pdfPath = pdfPaths.takeFirst();
QByteArray imageData = imageDatas.takeFirst();
QString ocrUrl = QString("https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token=%1").arg(accessToken);
QNetworkRequest ocrRequest(QUrl(ocrUrl));
ocrRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QByteArray postData;
postData.append("image=").append(QUrl::toPercentEncoding(imageData.toBase64()));
networkManager->post(ocrRequest, postData);
}
} else if (jsonObj.contains("words_result")) {
QJsonArray wordsResult = jsonObj["words_result"].toArray();
QString newFileName;
for (const auto &result : wordsResult) {
QJsonObject wordObj = result.toObject();
newFileName += wordObj["words"].toString();
}
if (!pdfPaths.isEmpty()) {
QString pdfPath = pdfPaths.takeFirst();
QFileInfo fileInfo(pdfPath);
QString newFilePath = fileInfo.dir().filePath(newFileName + ".pdf");
QFile::rename(pdfPath, newFilePath);
ui->resultTextEdit->append("Renamed: " + pdfPath + " to " + newFilePath);
}
}
} else {
ui->resultTextEdit->append("Network error: " + reply->errorString());
}
reply->deleteLater();
}
4. 头文件 mainwindow.h
cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QList>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void selectDirectory();
void onNetworkReplyFinished(QNetworkReply *reply);
private:
Ui::MainWindow *ui;
QNetworkAccessManager *networkManager;
QList<QString> pdfPaths;
QList<QByteArray> imageDatas;
void processPDF(const QString &pdfPath);
};
#endif // MAINWINDOW_H
注意事项
- 请将
your_api_key
和your_secret_key
替换为你自己的百度云 OCR API Key 和 Secret Key。 - 代码中假设要提取的局部区域为
QRect(100, 100, 200, 50)
,你需要根据实际情况调整该区域。 - 本方案依赖于
Poppler
库进行 PDF 转图片操作,需要确保该库已正确安装并配置。