Как извлечь текст из файлов .doc, .docx, .xlsx, .pptx с помощью PHP
Описание проблемы:
Существует задача, при которой необходимо извлекать текст из загруженных пользователями документов Word для дальнейшего поиска по строкам, например, в резюме. Однако возникает общая проблема: как получить текст, открыть и прочитать загруженный пользователем документ Word. Есть несколько полезных ссылок, но они не решают всю проблему. Нам нужно извлечь текст во время загрузки документа и сохранить его в базе данных, чтобы мы могли легко производить поиск в базе данных.
Как правильно реализовать этот процесс, чтобы избежать сложностей с обработкой документов и обеспечить корректное сохранение текста для последующего поиска?
3 ответ(ов)
Вопрос: Как извлечь текст и адреса электронной почты из файлов формата DOC и DOCX с помощью PHP?
Ответ:
Вы можете использовать следующий код для извлечения текста и адресов электронной почты из файлов DOC и DOCX. Вот как это можно сделать:
Для файлов DOC:
$filename = 'your_file.doc';
if (file_exists($filename)) {
if (($fh = fopen($filename, 'r')) !== false) {
$headers = fread($fh, 0xA00); // Чтение заголовков файла
// Вычисление длины текста
$n1 = (ord($headers[0x21C]) - 1);
$n2 = ((ord($headers[0x21D]) - 8) * 256);
$n3 = ((ord($headers[0x21E]) * 256) * 256);
$n4 = (((ord($headers[0x21F]) * 256) * 256) * 256);
$textLength = ($n1 + $n2 + $n3 + $n4);
$extracted_plaintext = fread($fh, $textLength); // Извлечение текста
echo nl2br($extracted_plaintext); // Вывод текста с переносами строк
print_r(extract_emails_from($extracted_plaintext)); // Извлечение и вывод адресов электронной почты
}
}
// Функция для извлечения адресов электронной почты
function extract_emails_from($string) {
preg_match_all("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i", $string, $matches);
return $matches[0]; // Возвращаем массив найденных email
}
Для файлов DOCX:
$document = 'your_file.docx'; // Название файла
// Функция для извлечения текста
function extracttext($filename) {
// Проверка расширения файла
$ext = pathinfo($filename, PATHINFO_EXTENSION);
// Определение файла данных в зависимости от расширения
if ($ext == 'docx') {
$dataFile = "word/document.xml";
} else {
$dataFile = "content.xml"; // Для формата ODT
}
// Создание нового объекта ZIP архив
$zip = new ZipArchive;
// Открытие архивного файла
if (true === $zip->open($filename)) {
// Поиск файла данных в архиве
if (($index = $zip->locateName($dataFile)) !== false) {
// Чтение файла данных в строку
$text = $zip->getFromIndex($index);
// Загрузка XML из строки
$xml = DOMDocument::loadXML($text, LIBXML_NOENT | LIBXML_XINCLUDE | LIBXML_NOERROR | LIBXML_NOWARNING);
// Удаление тегов форматирования и возврат текста
return strip_tags($xml->saveXML());
}
// Закрытие архивного файла
$zip->close();
}
// В случае ошибки возвращаем сообщение
return "Файл не найден";
}
echo extracttext($document); // Выводим извлеченный текст
Обратите внимание, что для работы с DOCX файлами используется класс
ZipArchive
для доступа к содержимому файла в формате ZIP. Убедитесь, что у вас установлен расширениеZip
для PHP. Также стоит позаботиться о том, что текст может содержать определенные теги, поэтому используйтеstrip_tags
для очистки.
Если вы хотите сохранить пробелы при извлечении текста из документов формата DOCX, а также правильно обрабатывать таблицы (элементы <w:tr>
и <w:tc>
), используйте следующий код. Он загружает файл с удаленного или локального адреса и работает с содержимым DOCX:
//=========DOCX===========
function extractDocxText($url, $file_name) {
$docx = get_url($url);
file_put_contents("tempf.docx", $docx);
$xml_filename = "word/document.xml"; // имя файла с содержимым
$zip_handle = new ZipArchive;
$output_text = "";
if (true === $zip_handle->open("tempf.docx")) {
if (($xml_index = $zip_handle->locateName($xml_filename)) !== false) {
$xml_datas = $zip_handle->getFromIndex($xml_index);
// Заменяем элементы на соответствующие символы
$replace_newlines = preg_replace('/<w:p w[0-9-Za-z]+:[a-zA-Z0-9]+="[a-zA-z"0-9 :="]+">/', "\n\r", $xml_datas);
$replace_tableRows = preg_replace('/<w:tr>/', "\n\r", $replace_newlines);
$replace_tab = preg_replace('/<w:tab\/>/', "\t", $replace_tableRows);
$replace_paragraphs = preg_replace('/<\/w:p>/', "\n\r", $replace_tab);
$replace_other_Tags = strip_tags($replace_paragraphs);
$output_text = $replace_other_Tags;
} else {
$output_text .= "";
}
$zip_handle->close();
} else {
$output_text .= " ";
}
chmod("tempf.docx", 0777);
unlink(realpath("tempf.docx"));
// Сохранить в файл или вывести содержимое
file_put_contents($file_name, $output_text);
echo $output_text;
}
// Функция для получения URL, лучше чем file_get_contents()
function get_url($url, $timeout = 5) {
$url = str_replace("&", "&", urldecode(trim($url)));
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001 Firefox/0.10.1");
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_ENCODING, "");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // требуется для HTTPS URL
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
$content = curl_exec($ch);
curl_close($ch);
return $content;
}
Не забудьте адаптировать код под свои нужды, так как это пример для извлечения текста только из формата DOCX. Если у вас есть дополнительные вопросы или необходима помощь с другими форматами (PDF, DOC, XLSX, PPTX и т.д.), дайте знать!
Для работы с документами формата .docx
я рекомендую использовать инструмент docx2txt
, который доступен, как минимум, в системах Debian/Ubuntu:
docx2txt < ваш_файл.docx
В файле README
объясняется, как интегрировать его с Vim. Добавьте в ваш файл .vimrc
следующие строки:
" используйте docx2txt.pl, чтобы позволить Vim просматривать текстовое содержимое .docx файла напрямую.
autocmd BufReadPre *.docx set ro
autocmd BufReadPost *.docx %!docx2txt
(Также объясняется, как интегрировать инструмент с Emacs).
Для тех, кто интересуется техническими подробностями, этот инструмент написан на Perl.
Функции startsWith() и endsWith() в PHP
Как получить расширение файла в PHP?
Как читать большой файл построчно?
ReCaptcha 2.0 с использованием AJAX
Почему нельзя вызывать абстрактные функции из абстрактных классов в PHP?