Комментарии 10
Интересная статья, не знал, что у hh есть api. Было бы прикольней парсить вакансии с хабра, а также например визуализировать график по вакансиям. Я так понимаю пагинацию не учитывает автор, поэтому добавил бы ее
Спасибо за идею, но сам Бог велел запилить сие чудо на модном Питоне...
И нафига в этой задаче особая многопоточность, хотя она и в Питоне есть?
Изначально была идея реализация парсинга вакансий с пагинацией, поэтому и была реализована многопоточность. Статей про парсинг на python много на Хабре, а на другом ЯП встречаются редко, поэтому и было реализовано.
"private protected static List ParseData" - даже в Яве не додумались смешивать private и protected. А я кодю на Питоне, и этой машны не пишу. Я то ожидал, что чудо программу можно будет скачать, ан нет. Но я через апи hh.ru написал всё, что мне было нужно.
"private protected static List ParseData"
Если вы не понимаете смысл какой-то конструкции языка, который вы не используете, зачем об этом оповещать всех остальных? Ведь иначе бы они о вашем незнании и не догадывались. Или вы гордитесь своим незнанием?
А я кодю на Питоне, и этой машны не пишу.
Если вам нравится писать именно на Python - пишите на Python, и не тратьте время и силы на комментирование статьи про разбор на других языках. Или вам обязательно нужно, чтобы и все остальные писали на Python? Не могу понять зачем вообще такое нужно: был бы Python коммерчиским - там понятно: владельцам продукта нужно, чтобы больше денежек им капало. Но для некоммерческого-то продукта это зачем?
Но я через апи hh.ru написал всё, что мне было нужно.
Я за вас искренне рад. Но мне вот больше нравится C#. Однако свои предпочтения я навязывать никому не буду, да.
Асинхронность обеспечила плавную работу интерфейса даже при массовом парсинге.
Строгая типизация свела к минимуму runtime-ошибки.
WPF позволил создать desktop-приложение с продвинутым UI без зависимости от веб-технологий.
При чем тут модный питон?
за, более, чем четверть века периодического парсинга и чтения статей, да книжек, посвященных этой теме, я насмотрелся всяких выражений - и "распарсить", и "отпарсить", и "выпарсить", но "спарсить" вижу впервые.
хотелось бы понять, с чем связан выбор данного терминологического артефакта.
Что мне не понравилось в статье - это плашка Tutorial.
Потому что статья учит объективно плохому.
И это даже не про архитектуру - хотя у меня и там возникли замечания.
Самое плохое, чему учит статья - это небрежной работе с асинхронными методами в GUI-приложении(WPF, в частности). Я вообще плохо понимаю, как можно писать про асинхронное выполнение в программе на WPF, совершенно не упоминая контекст синхронизации (SynchronizationContext) приложения - который в WPF однопоточный. А ведь выполнение асинхронных вызовов в таких условиях - это как хождение по минному полю: шаг влево, шаг вправо - и здравствуйте, непредсказуемые последствия. Например, вы совершенно не поясняете, зачем вы запускаете разбор страниц так: await Task.Run(() => ParsingPages(link));
И если кто-то из изучающих вопрос, основываясь на вашей статье, решит что ParsingPages сам по себе возвращает задачу, а потому Task.Run тут не нужен, и напишет вместо этого await ParsingPages(link);
то его может ждать неприятный сюрприз в виде блокировки потока GUI (тем более, что блокировка потока у вас там есть в явном виде, на вызове WaitOne()). А если он же где-нибудь вычитает, что от блокировки потока на await ему поможет избавиться ConfigureAwait, и попытается исправить, написав await ParsingPages(link).ConfigureAwait(false);
то сюрприз, но уже другой, его может ждать, когда он из этого же асинхронного метода попытается поменять что-нибудь в GUI (а, насколько я понял, у вас там это делается). IMHO не рассматривать такие вещи в статье, претендующей на роль руководства, недопостимо.
Ну и ещё, чтобы два раза не вставать. Вы пишете, что вы исползуете SemaphoreSlim. Это хорошо, это правильно. Но используете вы его неправильно: блокируете в асинхронном методе поток, делая на нем WaitOne. Тогда как SemaphoreSlim имеет метод WaitAsync, возвращающий Task, на которой в асинхронном методе можно сделать await и тем самым - вообще не блокировать поток. Я не знаю, позволяют ли испольуемые вами библиотеки запускать асинхронные операции, не занимающие надолко поток, в котором эти операции были вызваны (хорошие, годные библиотеки - позволяют: если им надо занять какой-нибудь поток надолго, то они эту часть своего кода запустят в другом потоке, и возобновление после долгого ожидания они тоже разрешат делать в другом потоке с помощью того же ConfigureAwait(false)). Но если библиотеки такое позволяют, то использование асинхронного ожидания на SemaphoreSlim вместо синхронного могло бы позволить вам вообще отказаться от упомянутого выше Task.Run и даже забыть про SynchronizationConteхt (хотя лучше про него всё-таки помнить).
От данных к интерфейсу: как спарсить вакансии с HH и SuperJob на C#