Поиск и преобразование файлов HTML и перемещение их в массовом порядке - PullRequest
6 голосов
/ 15 ноября 2011

Я использую Mathematica для работы с большим массивом файлов веб-сайта, которые я отразил на моей собственной системе. Они распределены по нескольким сотням каталогов с тоннами подкаталогов. Так, например, у меня есть:

/users/me/test/directory1
/users/me/test/directory1/subdirectory2 [times a hundred]
/users/me/test/directory2
/users/me/test/directory2/subdirectory5 [etc. etc.]

Что мне нужно сделать, это зайти в каждый каталог, Import[] все файлы HTML в виде открытого текста, а затем поместить их в другой каталог в другом месте моей системы с именем «directory1». До сих пор с циклами Do[] я смог сделать черновую версию: однако, лучший вариант, который у меня есть сейчас, - это сбросить файлы .txt в исходный каталог, что не является идеальным решением, так как они Вы все еще распространены по всей моей системе.

Чтобы найти мои файлы, я использую directoryfiles = FileNames["*.htm*", {"*"}, Infinity];

Некоторые дополнительные неприятные проблемы:

(1) Дубликаты: есть ли у Mathematica способ справиться с дубликатами - то есть, если мы столкнемся с другим index_en.html, можно ли его переименовать в index_en_1.html?

(2) Каталоги: Из-за всех каталогов, если я не использую Mathematica постоянно SetDirectory и CreateDirectory снова и снова, он продолжает сталкиваться с проблемами.

Все это немного сбивает с толку. По сути, существует ли эффективный способ для Mathematica найти тонну HTML-файлов, распределенных по сотням каталогов / подкаталогов, импортировать их в виде открытого текста и экспортировать их в другое место [для меня важно знать, что они пришли из directory1, но это все] ,

- отредактировано для ясности ниже -

Вот код, который у меня сейчас есть:

SetDirectory[
  "/users/me/web/"];
dirlist = FileNames[];
directoryPrefix = 
  "/users/me/web/";
plainHTMLBucket = "";
Do[
  directory = directoryPrefix <> dirname;
  exportPrefix = 
   "/users/me/desktop/bucket/";
  SetDirectory[directory];
  allFiles = FileNames["*.htm*", {"*"}, Infinity];
  plainHTMLBucket = "";
  Do[
   plainHTML = Import[filename, "Plaintext"];
   plainHTMLBucket = AppendTo[plainHTMLBucket, plainHTML];
   , {filename, allFiles}];
  Export[exportPrefix <> dirname <> ".txt", plainHTMLBucket];
  Print["We Have Reached Here"];
  , {dirname, dirlist}];

Что не так с моей точки зрения? Помимо того, что это беспорядок, это мой обходной путь: я бы предпочел разделить все файлы, а не один большой - т.е. взять каждый импорт и экспорт как отдельный файл, но в каталоге с именем 'directory1', хотя и где-нибудь еще. Проблема в том, что когда дело доходит до зеркалирования этих каталогов (каталоги не существуют, но у меня возникают проблемы с использованием CreateDirectory[] для динамического выполнения).

Мои извинения за путаницу здесь - я знаю, что это показывает с этим вопросом ..

Ответы [ 2 ]

8 голосов
/ 15 ноября 2011

Следующий код может помочь:

mapFileNames[source_, filenames_, target_] :=
  Module[{depth = FileNameDepth[source]}
  , FileNameJoin[{target, FileNameDrop[#, depth]}]& /@ filenames
  ]

htmlTreeToPlainText[source_, target_] :=
  Module[{htmlFiles, textFiles, targetDirs}
  , htmlFiles = FileNames["*.html", source, Infinity]
  ; textFiles = StringReplace[
                  mapFileNames[source, htmlFiles, target]
                  , f__~~".html"~~EndOfString :> f~~".txt"
                  ]
  ; targetDirs = DeleteDuplicates[FileNameDrop[#, -1]& /@ textFiles]
  ; If[FileExistsQ[target], DeleteDirectory[target, DeleteContents -> True]]
  ; Scan[CreateDirectory[#, CreateIntermediateDirectories -> True]&, targetDirs]
  ; Scan[
      Export[#[[2]], Import[#[[1]], "Plaintext"], "Text"] &
    , Transpose[{htmlFiles, textFiles}]
    ]
  ]

Пример использования ( предупреждение : целевой каталог будет удален первым! ):

htmlTreeToPlainText["/users/me/web", "/users/me/desktop/bucket"]

Как это работает

Различные функции Mathematica FileName... полезны в этом контексте.Сначала мы определяем вспомогательную функцию mapFileNames, которая принимает исходный каталог, список имен файлов, которые находятся в исходном каталоге, и целевой каталог.Он возвращает список путей к файлам, которые называют соответствующие местоположения под целевым каталогом.

mapFileNames[source_, filenames_, target_] :=
  Module[{depth = FileNameDepth[source]}
  , FileNameJoin[{target, FileNameDrop[#, depth]}]& /@ filenames
  ]

Функция использует FileNameDrop, чтобы отбрасывать ведущие элементы исходного пути из каждого имени файла, и FileNameJoin, чтобы добавить целевую точкупуть на фронт каждого результата.Количество ведущих элементов для отбрасывания определяется путем применения FileNameDepth к исходному пути.

Например:

In[83]:= mapFileNames["/a/b", {"/a/b/x.txt", "/a/b/c/y.txt"}, "/d"]
Out[83]= {"/d/x.txt", "/d/c/y.txt"}

Используя эту функцию, мы можем преобразовать список путей к файлам HTMLв исходном каталоге (source) в соответствующий список путей текстовых файлов в целевом каталоге (target):

htmlFiles = FileNames["*.html", source, Infinity]

textFiles = StringReplace[
              mapFileNames[source, htmlFiles, target]
              , f__~~".html"~~EndOfString :> f~~".txt"
              ]

Эти операторы получают список файлов HTML, сопоставляют их с целевым каталогоми затем измените расширение файла с .html на .txt.Теперь мы можем извлечь необходимые имена каталогов из полученных текстовых файлов:

targetDirs = DeleteDuplicates[FileNameDrop[#, -1]& /@ textFiles]

Снова используется FileNameDrop, на этот раз для удаления части имени файла из пути каждого текстового файла.

Далеенам нужно удалить целевой каталог (если он уже существует) и создать новые требуемые каталоги:

If[FileExistsQ[target], DeleteDirectory[target, DeleteContents -> True]]

Scan[CreateDirectory[#, CreateIntermediateDirectories -> True]&, targetDirs]

Теперь мы можем выполнить преобразование HTML в текст, безопасное при условии, что целевые каталогиуже существует:

Scan[
  Export[#[[2]], Import[#[[1]], "Plaintext"], "Text"] &
, Transpose[{htmlFiles, textFiles}]
]
4 голосов
/ 15 ноября 2011

Чтобы установить текущий каталог, сделайте что-то вроде

SetDirectory["~/Desktop/"]

Теперь предположим, что я хочу получить список всех каталогов в текущем каталоге.Я могу сделать

dirs=Pick[
   #,
   (FileType[#] == Directory) & /@ #
   ] &@FileNames[]

, который возвращает список имен всех каталогов в текущем каталоге, который вы установили ранее (я использую вложенные чистые функции, которые могут сбивать с толку ...).Затем вы можете сделать fn для каждого из dirs на Scan[fn,dirs].Таким образом, вы могли бы назначить конструкцию Pick[] для функции, а затем использовать ее для восстановления своего дерева.

Это просто, но я не уверен, что это то, что вы хотите.Может быть, вы могли бы быть немного более точным в том, что вы ищете, поэтому я / мы не садимся и не пишем неправильные вещи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...