Страницы

Поиск по вопросам

суббота, 27 апреля 2019 г.

Конвертировать текст на русском из pdf в txt python

Пытаюсь конвертировать кирилицу из pdf в txt c помощью PyPDF2 в Python
import PyPDF2 pdf_file = open('mail_cir.pdf', 'rb') read_pdf = PyPDF2.PdfFileReader(pdf_file) number_of_pages = read_pdf.getNumPages() page = read_pdf.getPage(0) page_content = page.extractText() print (page_content.encode('utf-8'))
Ошибки не выдает, но и текст не видит.
Пыталась изменить:
pdf_file = codecs.open('mail_cir.pdf', 'rb', encoding='utf-8')
Тогда выдается ошибка:
TypeError: Can't convert 'bytes' object to str implicitly
И другой вопрос:
Если конвертировать стих, то после окончания строки на пустом месте выводится

. Как избавиться от этих символов?


Ответ

Можно воспользоваться PDFMiner, чтобы текст, включающий русские буквы, из pdf достать:
#!/usr/bin/env python import sys import pdfminer.high_level # $ pip install pdfminer.six
with open('mail_cir.pdf', 'rb') as file: pdfminer.high_level.extract_text_to_fp(file, sys.stdout)
pdf2txt.py показывает как эта функция может быть использована—можно много опций передать.
Ввод (в pdf)
English 🇬🇧 На русском 🇷🇺 Smiley: ☺ non-BMP smiley: 😂
Вывод (текст в консоли)
English На русском Smiley: ☺non-BMP smiley:
Русский текст нормально извлёкся, но non-BMP смайлик 😂 (U+1F602) и флаги 🇬🇧 (U+1F1EC U+1F1E7), 🇷🇺 (U+1F1F7 U+1F1FA) потерялись при конвертации.

Код с PyPDF2, похожий на приведённый в вопросе, смог извлечь только символы в ASCII диапазоне.

JQuery. Поворот изображения туда-обратно

Доброго времени суток! Не могу сообразить, как реализовать поворот картинки на 45 и -45 градусов непрерывано, то есть, картинка все время наклоняется то в одну, то в другую сторону. Пока только при наведении мыши реализовано:


Ответ

Позволил себе чуть изменить код Abmin чтобы подходил по условию:
#me { -webkit-animation: rotation 2s infinite linear; padding: 20px; } @-webkit-keyframes rotation { 0% { -webkit-transform: rotate(0deg); } 50% { -webkit-transform: rotate(90deg); } 100% { -webkit-transform: rotate(0deg); } }

Получение кода символа

int main(void) {
printf("%d",(int)'А'); }
По идее, программа должна вывести код 'А'(кириллица), т.е. 192, но почему-то выводит -64.


Ответ

Тип char может вести себя либо как тип signed char либо как тип unsigned char в зависимости от установленных опций компилятора.
В вашем случае тип char ведет себя как тип signed char
Для типа signed char максимальное положительное значение равно 127 или в шестнадцатиричной форме 0x7F
Если хотите получить положительное значения кода, то напишите
printf("%d",(unsigned char)'А');
При этом русская буква не должна быть представлена как многобайтная константа.

Почему алиас «cd» работает так странно?

Хотел сделать алиас cd, который будет сразу перечислять директории.
Попробовал все следующие варианты:
alias 'cd'='cd $1; l' alias 'cd'='cd $1; l $1' alias 'cd'='cd $1 && l' alias 'cd'='cd $1 && l $1'
Где, l (строчная «L») — алиас другого приложения (tree).
Всегда перегружал терминал, чтобы наверняка, так как . ~/.bash_aliases у меня почему-то не срабатывает.
Все вышеперечисленные алиасы при вводе cd / перечисляют список директорий / файлов в точке монтирования /, однако смена директории не происходит.
Тогда я попробовал прописать в том же .bash_aliases функцию (оба варианта, по очереди):
cd() { cd $1 l }
function cd() { cd $1 l }
В итоге, при выполнении cd / команда «виснет» ...
Единственный способ, который я нашёл, это сделать так:
cdl() { cd $1 l }
То есть задать другое имя ... Но в тоже время, если вернуться к первому варианту алиаса:
alias 'cd'='cd $1; l'
Здесь же срабатывает cd при вводе cd /, так как l перечисляет список директорий / файлов по пути /, так почему же тогда он возвращает обратно в домашнюю директорию?


Ответ

псевдоним оболочки (shell alias) — это не функция и не программа. у псевдонима нет аргументов, его описание всего лишь подставляется в команду вместо его имени. поэтому, если вы определили, например, такой псевдоним
$ alias cd='cd $1; ls'
то при вводе команды
$ cd /tmp
она преобразуется в
$ cd ; ls /tmp
обратите внимание на пустое место после cd — туда ничего не будет подставлено (вместо $1), т.к. переменная $1 не содержит никакого значения.
в результате вашим текущим каталогом станет ваш домашний каталог (так действует внутренняя команда cd, если ей не передать никаких параметров), а затем будет выполнена команда ls /tmp когда вы определяете функцию:
$ function cd() { cd $1; ls; }
команда cd $1 внутри её тела трактуется как рекурсивное обращение к этой же функции, вот и происходит «зависание». кстати, обратите внимание, что в теле псевдонима не происходит такой рекурсии — cd $1 там трактуется именно как обращение к внутренней команде оболочки cd

и напоследок, в виде факультативного дополнения к ответу на вопрос «почему», приведу пример того, как сделать, чтобы «работало так, как хочется»:
$ function cd() { command cd "$@"; ls; }
использовать надо именно функцию (кстати, само ключевое слово function в данном случае — опционально), чтобы получить и обработать список аргументов. для вызова внутренней команды оболочки надо использовать внутреннюю же команду command правильнее передавать не только первый аргумент, а все аргументы ($@), а чтобы корректно обрабатывались спец-символы (например, пробелы/кавычки и т.п.) внутри аргументов, список лучше заключить в двойные кавычки ("$@").

MVVM для начинающих

Пытаюсь вникнуть в суть MVVM, рассматривая простейшие примеры и мне непонятны некоторые вещи,такие как:
public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName]string prop = "") { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
Также непонятно как работает интерфейс INotifyPropertyChanged Может ли кто-нибудь все это объяснить? P.S. на MSDN и других сайтах был и читал,но понятнее не стало


Ответ

Попробую объяснить.
Между View(графический интерфейс программы (кнопки, текстовые поля, и проч.)) с помощью так называемого байдинга (кто-то называет биндинг, хотя это неправильное произношение) устанавливается связь со свойствами во ViewModel. Например с текстовым полем ввода мы связываем свойство (ViewModel) - public string Name { get; set; } с помощью записи в XAML (View) Для этого во ViewModel реализуют (наследуют) от стандартного интерфайса INotifyPropertyChanged. В вашем примере используется один из вариантов такой реализации:
public event PropertyChangedEventHandler PropertyChanged; - собственно само объявление нужного события.
public void OnPropertyChanged([CallerMemberName]string prop = "") - вспомогательный метод для вызова этого события из блока set;
[CallerMemberName] - атрибут у параметра, который позволяет не указывать название свойства программисту, компилятор сам подставит имя свойства, которое вызывает метод OnPropertyChanged, т.е. вы можете вызвать как OnPropertyChanged("Name") или же так OnPropertyChanged() и тогда ("Name") вместо вас подставит компилятор.
Далее в самом методе происходит проверка; а если ли у этого события подписчики? И в случае наличия таковых (у нас это Такой вариант вызова события не единственный, в интернетах и в книгах можно найти еще пару-тройку вариантов. Все это дело вкусовщины. Лично я люблю прямой вызов события, что называется "в лоб", покажу на примере, может вам станет все еще яснее.
public class MainViewModel : INotifyPropertyChanged //не забываем о наследовании
Присваиваем в объявлении события пустой делегат, чтобы потом не заниматься проверкой, а если ли подписанты на событие? Они теперь всегда есть, по крайней мере один пустой подписант.
public event PropertyChangedEventHandler PropertyChanged = delegate { };
А вот пример свойства с вызовом этого события (использую новую конструкцию nameof(), чтобы передать название свойства)
///

/// Имя скачиваемого видео файла /// private string _NameFileVideo; public string NameFileVideo { get { return _NameFileVideo; } set { if (_NameFileVideo == value) return; _NameFileVideo = value; PropertyChanged(this, new PropertyChangedEventArgs(nameof(NameFileVideo))); } }

Порядок выполнения git commit и git pull

Недавно начал работать с гитом. Какая разница сделать pull до commit или после commit, и есть ли она вообще?


Ответ

В целом разницы нет. Если конфликта в ваших изменениях и изменениях из upstream не будет, то все пройдет без вопросов. Если же возникнет конфликт слияния, git так или иначе сообшит об этом, и вам в любом случае придется его решать.
Но я бы предпочел сначала сделать коммит, чтобы зафиксировать изменения. Тогда легко можно будет откатиться к исходной версии ваших изменений, если что-то пойдет не так.
Если коммит по каким-то причинам делать не хочется (например, работа не завершена), можно временно спрятать изменения командой git stash, потом сделать git pull, а потом вернуть изменения командой git stash apply. Этому посвящен отдельный раздел в документации

Перебор файлов и копирование в определенную папку

Как вызвать метод List?
public static void SearchAllFiles() { List files = new List(); String[] extensions = new String[] { "*.jpg", "*.txt", "*.asp" };
foreach (String extension in extensions) { String[] files = Directory.GetFiles(path, found, SearchOption.AllDirectories);
foreach (String file in files) files.Add(file); } }
И не могу сообразить в каком месте вставить копирование файлов:
File.Copy(path, path + Path.GetFileName(path));


Ответ

Для начала сделаем метод для поиска файлов по маске. Работает с .NET 4.0 и быстрее, чем Directory.GetFiles
public static IEnumerable nGetFiles(string path, string searchPatternExpression = "", SearchOption searchOption = SearchOption.AllDirectories) { Regex reSearchPattern = new Regex(searchPatternExpression); return Directory.EnumerateFiles(path, "*", searchOption).Where(file => reSearchPattern.IsMatch(Path.GetFileName(file))); }
Теперь так:
public static void SearchAllFiles() { //Искомые расширения: string LookForExt = "\.jpg|\.txt|\.asp"; //Пути папок источника и приёмника: string SourcePath = @"D:\SourceDir\"; string TargetPath = @"D:\TargetPath\"; //Получаем файлы и копируем их: IEnumerable files = nGetFiles(SourcePath, LookForExt); foreach (f in files) //Можно было и так: foreach (f in nGetFiles(@"D:\SourceDir", LookForExt)) { try { File.Copy(f, TargetPath + Path.GetFileName(f), true); } catch (Exception e) { throw e; } } }
В результате будут просканированы все файлы в папке SourcePath и ее подпапках, найденные файлы, соответствующие искомым расширениям будут скопированы в TargetPath без сохранения структуры подпапок. Более того, если есть файл D:\SourceDir\test.asp и есть файл D:\SourceDir\111\test.asp, то в результирующей папке D:\TargetPath\ будет только один из этих файлов, который будет копироваться последним (он и перезатрёт существующий, и скопированный первым в целевую папку файл).
Если же нужно скопировать файлы из папки с сохранением структуры вложенных папок и файлов, то вот тут уже давал ответ