С помощью нескольких простых скриптов вы можете легко очистить документы и другие большие HTML-файлы. Но сначала их нужно разобрать.
Как давний член группы документации Scribus, я постоянно в курсе последних обновлений исходного кода, чтобы документацию можно было обновлять и дополнять. Когда я недавно проверил Subversion на компьютере, который только что был обновлен до Fedora 27, я был поражен тем, сколько времени ушло на загрузку документации, состоящей из HTML-страниц и связанных изображений. Я боюсь, что документация проекта выглядит намного больше, чем сам проект, и подозреваю, что часть ее содержимого является документами-зомби — HTML-файлы, которые больше не используются, и изображения, недоступные в HTML.
Я решил создать проект для себя, чтобы решить эту проблему. Одним из способов является поиск существующих файлов изображений, которые не используются. Если бы я мог сканировать все HTML-файлы на наличие ссылок на изображения, а затем сравнивать этот список с фактическими файлами изображений, я мог бы увидеть файлы, которые не совпадают.
Вот типичный тег изображения:
<img src="images/edit_shapes.png" ALT="Edit examples" ALIGN=left>
я правsrc=
Часть между первым набором кавычек после того, как представляет интерес. После поиска некоторых решений я нашел один под названиемBeautifulSoupмодуль Python. Основная часть скрипта выглядит так:
soup = BeautifulSoup(all_text, 'html.parser')
match = soup.findAll("img")
if len(match) > 0:
for m in match:
imagelist.append(str(m))
мы можем использовать этоfindAll
метод, чтобы выкопать теги изображения. Вот небольшая часть вывода:
<img src="images/pdf-form-ht3.png"/><img src="images/pdf-form-ht4.png"/><img src="images/pdf-form-ht5.png"/><img src="images/pdf-form-ht6.png"/><img align="middle" alt="GSview - Advanced Options Panel" src="images/gsadv1.png" title="GSview - Advanced Options Panel"/><img align="middle" alt="Scribus External Tools Preferences" src="images/gsadv2.png" title="Scribus External Tools Preferences"/>
Все идет нормально. Я думал, что следующий шаг поможет, но когда я попробовал некоторые строковые методы в скрипте, он вернул ошибку о токене вместо строки. Я сохраняю вывод в файл и помещаю его вKWriteредактировать в. Одна из приятных особенностей KWrite заключается в том, что вы можете использовать регулярные выражения (регулярные выражения) для выполнения операций «найти и заменить», поэтому я могу использовать\n<img
заменять<img
, чтобы вы могли видеть это более четко.
Еще одна приятная особенность KWrite заключается в том, что если вы сделаете неразумный выбор с помощью регулярных выражений, вы можете отменить его.
Но я подумал, что должно быть что-то лучше этого, поэтому я обратился к регулярным выражениям, а точнее к Python.re
модуль. Соответствующая часть этого нового скрипта выглядит так:
match = re.findall(r'src="(.*)/>', all_text)
if len(match)>0:
for m in match:
imagelist.append(m)
Небольшая часть его вывода выглядит так:
images/cmcanvas.png" title="Context Menu for the document canvas" alt="Context Menu for the document canvas" /></td></tr></table><br images/eps-imp1.png" title="EPS preview in a file dialog" alt="EPS preview in a file dialog" images/eps-imp5.png" title="Colors imported from an EPS file" alt="Colors imported from an EPS file" images/eps-imp4.png" title="EPS font substitution" alt="EPS font substitution" images/eps-imp2.png" title="EPS import progress" alt="EPS import progress" images/eps-imp3.png" title="Bitmap conversion failure" alt="Bitmap conversion failure"
На первый взгляд, он похож на вывод выше, с дополнительным преимуществом удаления части изображения с метками, но загадочным образом перемежается метками таблиц и другими вещами. Я думаю, что это связано с этим регулярным выражениемsrc="(.*)/>
, который называетсяжадный, это означает, что он не обязательно останавливается на встрече/>
первый экземпляр . Я должен добавить, что я также пыталсяsrc="(.*)"
, это действительно не намного лучше, я не эксперт по регулярным выражениям (только что сделал это) и искал различные способы улучшить это, но безрезультатно.
Сделав кучу вещей, даже попробовал PerlHTML::Parser
модуль, и, в конечном счете, я пытаюсь сравнить это с некоторыми сценариями, которые я написал для Scribus, которые анализируют текстовое содержимое посимвольно, а затем выполняют некоторые действия. В конце концов, я наконец понял все эти методы без необходимости использования регулярных выражений или синтаксических анализаторов HTML. Вернемся к показанномуimg
Примеры этикеток.
<img src="images/edit_shapes.png" ALT="Edit examples" ALIGN=left>
Я решил вернуться кsrc=
этот кусок. Один из способов - подождатьs
появляется, затем проверьте, является ли следующий символr
, следующийc
, будь то следующий=
. Если да, то это совпадение! Тогда содержимое между двумя двойными кавычками — это то, что мне нужно. Проблема с этим подходом заключается в том, что структуры, подобные приведенным выше, необходимо постоянно идентифицировать. Один из способов посмотреть на строку, представляющую строку текста HTML:
for c in all_text:
Но эта логика слишком беспорядочна, чтобы продолжать сопоставлять предыдущуюc
, и символ перед, символ перед, символ перед больше.
Наконец, я решил сосредоточиться на=
и использовать метод индекса, чтобы я мог легко ссылаться на любой предыдущий или будущий символ в строке. Вот раздел поиска:
index = 3
while index < linelength:
if (all_text[index] == '='):
if (all_text[index-3] == 's') and (all_text[index-2] == 'r') and (all_text[index-1] == 'c'):
imagefound(all_text, imagelist, index)
index += 1
else:
index += 1
else:
index += 1
Я начинаю поиск с четвертого символа (индексация начинается с 0), поэтому я не получаю ошибку индексации ниже, и фактически перед четвертым символом в каждой строке не будет знака равенства. Первый тест должен увидеть, появляется ли строка=
, если нет, то движемся вперед. Если мы видим знак равенства, то проверяем, совпадают ли первые три символа.s
,r
иc
. Если все совпадает, вызываем функциюimagefound
:
def imagefound(all_text, imagelist, index):
end = 0
index += 2
newimage = ''
while end == 0:
if (all_text[index] != '"'):
newimage = newimage + all_text[index]
index += 1
else:
newimage = newimage + '\n'
imagelist.append(newimage)
end = 1
return
Мы отправляем функции текущий индекс, который представляет=
. Мы знаем, что следующим персонажем будет"
, поэтому пропускаем два символа и начинаем вызыватьnewimage
Строка управления добавляет символы, пока мы не найдем следующий"
, на данный момент мы завершили матч. Мы добавляем новую строку в строку (\n
) добавить в списокimagelist
в и возвращение (return
), помните, что в остальной части этого HTML
В строке может быть больше тегов изображений, поэтому мы сразу возвращаемся к циклу поиска.
Вот как теперь выглядит наш вывод:
images/text-frame-link.png
images/text-frame-unlink.png
images/gimpoptions1.png
images/gimpoptions3.png
images/gimpoptions2.png
images/fontpref3.png
images/font-subst.png
images/fontpref2.png
images/fontpref1.png
images/dtp-studio.png
Ах, намного чище, и это занимает всего несколько секунд. Я мог бы переместить индекс на 7 шагов вперед, чтобы сократитьimages/
раздел, но я бы предпочел сохранить эту часть, чтобы убедиться, что я не отрезал первую букву имени файла изображения, которое легко успешно редактировать с помощью KWrite - вам даже не нужно регулярное выражение. После этого и сохранения файла следующим шагом будет запуск другого сценария, который я написал.sortlist.py
:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# sortlist.py
import os
imagelist = []
for line in open('/tmp/imagelist_parse4.txt').xreadlines():
imagelist.append(line)
imagelist.sort()
outfile = open('/tmp/imagelist_parse4_sorted.txt', 'w')
outfile.writelines(imagelist)
outfile.close()
Это читает содержимое файла, сохраняет в виде списка, сортирует его и сохраняет как другой файл. После этого я могу сделать следующее:
ls /home/gregp/development/Scribus15x/doc/en/images/*.png > '/tmp/actual_images.txt'
Затем мне нужно запустить этот файлsortlist.py
,так какls
Порядок методов отличается от Python. Я мог бы запустить скрипт сравнения этих файлов, но я бы предпочел сделать это визуально. В конце концов мне удалось найти 42 изображения, на которые не было HTML-ссылок из документации.
Вот мой полный скрипт разбора:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# parseimg4.py
import os
def imagefound(all_text, imagelist, index):
end = 0
index += 2
newimage = ''
while end == 0:
if (all_text[index] != '"'):
newimage = newimage + all_text[index]
index += 1
else:
newimage = newimage + '\n'
imagelist.append(newimage)
end = 1
return
htmlnames = []
imagelist = []
tempstring = ''
filenames = os.listdir('/home/gregp/development/Scribus15x/doc/en/')
for name in filenames:
if name.endswith('.html'):
htmlnames.append(name)
#print htmlnames
for htmlfile in htmlnames:
all_text = open('/home/gregp/development/Scribus15x/doc/en/' + htmlfile).read()
linelength = len(all_text)
index = 3
while index < linelength:
if (all_text[index] == '='):
if (all_text[index-3] == 's') and (all_text[index-2] == 'r') and
(all_text[index-1] == 'c'):
imagefound(all_text, imagelist, index)
index += 1
else:
index += 1
else:
index += 1
outfile = open('/tmp/imagelist_parse4.txt', 'w')
outfile.writelines(imagelist)
outfile.close()
imageno = len(imagelist)
print str(imageno) + " images were found and saved"
имя сценарияparseimg4.py
, что на самом деле не отражает количество сценариев, которые я написал подряд (как доработанных, так и переработанных, отброшенных и начатых заново). Обратите внимание, что я жестко запрограммировал эти каталоги и имена файлов, но их легко обобщить и позволить пользователю вводить эту информацию. Опять же, поскольку это рабочие сценарии, я отправляю вывод в/tmp
каталог, поэтому после перезагрузки системы они исчезнут.
Это не конец истории, потому что следующий вопрос: как HTML-файл Zombies? Любой неиспользуемый файл может быть указан изображением, не может найти предыдущий метод. у нас естьmenu.xml
файлы в качестве оглавления для онлайн-руководства, но мне также необходимо учитывать, что некоторые из файлов, перечисленных в оглавлении (аннотация LCTT: оглавление — это сокращение от оглавления), могут ссылаться на файлы, которых нет в оглавлении, да Я нашел кое-что из этого документа.
В итоге могу сказать, что это более легкая задача, чем поиск изображений, и процесс ее разработки мне очень помог.