Интересный результат получается, если сматчить биграммы полученные из топ20 выдачи, с биграммами из
запросов
$ /home/web/py/w2v/key.py
['град_пражский',
'площадь_староместский',
'карлов_мост',
'город_старый',
'святой_собор',
'вацлавская_площадь',
'тынский_храм',
'еврейский_квартал',
'дом_танцующий',
'башня_пороховой',
'место_стар',
'исторический_центр',
'маленький_страна',
'берег_левый',
'малый_страна',
'площадь_республика',
'место_нова',
'камп_остров',
'интересный_место',
'билет_входной',
'вар_карлов',
'место_стара',
'метро_станция',
'гора_кутна',
'метро_схема',
'отзыв_турист',
'виноград_район',
'проезд_схема',
'интересный_факт',
'петь_фонтан']
mystem "вацлавская" не умеет
$ mystem вацлавская вацлавская{вацлавская?} вацлавский вацлавский{вацлавский?} танцующие танцующие{танцующий|танцевать}
Devvver, "достопримечательности праги"
lsi/lda сюда, пока в консоль пишутся🙄
<class 'gensim.models.ldamodel.LdaModel'> num_topics=14 0.041*"прага" + 0.015*"место" + 0.015*"пражский" + 0.012*"большой" + 0.009*"город" + 0.008*"град" + 0.008*"район" + 0.008*"день" + 0.008*"человек" + 0.008*"очень" 0.026*"башня" + 0.017*"прага" + 0.015*"площадка" + 0.014*"бесплатно" + 0.012*"вид" + 0.011*"смотровой" + 0.011*"еврейский" + 0.010*"петршинский" + 0.010*"век" + 0.009*"красивый" 0.013*"век" + 0.012*"пражский" + 0.010*"храм" + 0.009*"ратуша" + 0.007*"музей" + 0.007*"галерея" + 0.007*"город" + 0.006*"располагать" + 0.006*"новый" + 0.006*"прага" 0.036*"прага" + 0.014*"год" + 0.012*"чехия" + 0.011*"уникальный" + 0.011*"святой" + 0.010*"деньги" + 0.008*"время" + 0.008*"музей" + 0.008*"стоить" + 0.007*"готический" 0.025*"прага" + 0.015*"площадка" + 0.013*"адрес" + 0.011*"место" + 0.011*"praha" + 0.010*"сад" + 0.009*"смотровой" + 0.009*"век" + 0.009*"лоретанский" + 0.008*"тратить" 0.020*"музей" + 0.015*"здание" + 0.011*"год" + 0.011*"площадь" + 0.010*"дворец" + 0.009*"дом" + 0.008*"известный" + 0.008*"построить" + 0.007*"век" + 0.007*"американский" 0.033*"прага" + 0.017*"музей" + 0.013*"год" + 0.011*"место" + 0.010*"национальный" + 0.010*"метр" + 0.010*"здание" + 0.009*"чешский" + 0.007*"театр" + 0.007*"длина" 0.052*"прага" + 0.022*"площадь" + 0.013*"пражский" + 0.011*"располагать" + 0.010*"староместский" + 0.010*"фото" + 0.009*"главный" + 0.009*"исторический" + 0.008*"район" + 0.008*"век" 0.018*"прага" + 0.012*"пражский" + 0.011*"град" + 0.011*"святой" + 0.009*"заставлять" + 0.009*"церковь" + 0.008*"чешский" + 0.007*"век" + 0.007*"район" + 0.007*"запрещать" 0.020*"год" + 0.011*"факт" + 0.009*"километр" + 0.008*"св" + 0.008*"москва" + 0.007*"чехия" + 0.007*"кладбище" + 0.007*"чешский" + 0.007*"знаменитый" + 0.006*"пражский" 0.018*"пражский" + 0.013*"зоопарк" + 0.013*"величие" + 0.011*"человек" + 0.011*"мельница" + 0.011*"музей" + 0.009*"место" + 0.009*"прага" + 0.008*"прочий" + 0.008*"право" 0.012*"окно" + 0.012*"азиатский" + 0.012*"площадь" + 0.011*"место" + 0.010*"рынок" + 0.009*"надпись" + 0.008*"располагать" + 0.008*"пражский" + 0.007*"дом" + 0.006*"карлова" 0.022*"прага" + 0.013*"чешский" + 0.010*"холм" + 0.009*"город" + 0.009*"место" + 0.008*"синагога" + 0.007*"красивый" + 0.007*"старый" + 0.006*"мост" + 0.006*"интересный" 0.036*"прага" + 0.028*"мост" + 0.018*"день" + 0.011*"коммунизм" + 0.010*"памятник" + 0.010*"карлова" + 0.009*"остров" + 0.009*"посмотреть" + 0.008*"располагать" + 0.008*"название" <class 'gensim.models.lsimodel.LsiModel'> num_topics=14 0.630*"прага" + 0.186*"год" + 0.180*"век" + 0.172*"пражский" + 0.165*"город" + 0.164*"место" + 0.150*"площадь" + 0.136*"здание" + 0.134*"чешский" + 0.129*"музей" 0.686*"прага" + -0.246*"пражский" + -0.244*"век" + -0.216*"год" + -0.175*"здание" + -0.143*"святой" + -0.135*"град" + -0.127*"стиль" + -0.110*"площадь" + -0.099*"собор" 0.636*"год" + -0.442*"пражский" + -0.310*"град" + 0.195*"музей" + 0.173*"здание" + -0.124*"век" + -0.106*"собор" + -0.099*"святой" + 0.090*"построить" + 0.086*"театр" 0.562*"площадь" + 0.271*"дом" + 0.253*"располагать" + -0.253*"пражский" + -0.232*"год" + 0.223*"здание" + 0.220*"староместский" + -0.179*"град" + -0.166*"мост" + -0.159*"чешский" 0.659*"мост" + 0.322*"место" + -0.281*"музей" + 0.208*"карлов" + 0.191*"башня" + -0.154*"здание" + 0.131*"город" + 0.104*"статуя" + -0.091*"стиль" + -0.090*"дворец" 0.503*"музей" + -0.317*"святой" + -0.250*"храм" + -0.242*"собор" + 0.194*"пражский" + -0.191*"век" + 0.184*"мост" + 0.159*"место" + 0.141*"еврейский" + -0.137*"башня" 0.506*"башня" + -0.372*"площадь" + -0.318*"святой" + 0.238*"век" + -0.166*"год" + 0.146*"смотровой" + -0.145*"собор" + -0.145*"место" + 0.143*"площадка" + 0.129*"вид" 0.436*"музей" + -0.348*"пражский" + 0.274*"век" + -0.242*"год" + -0.238*"здание" + -0.186*"дом" + 0.182*"святой" + 0.176*"город" + -0.171*"располагать" + 0.170*"храм" -0.372*"мост" + 0.323*"год" + -0.309*"здание" + 0.270*"башня" + 0.259*"город" + -0.226*"стиль" + 0.177*"пражский" + -0.168*"век" + -0.153*"дом" + 0.146*"площадь" 0.403*"еврейский" + 0.338*"старый" + -0.325*"башня" + -0.309*"музей" + 0.245*"синагога" + 0.199*"кладбище" + 0.172*"век" + -0.168*"чешский" + 0.157*"район" + -0.152*"площадь" -0.481*"чешский" + -0.443*"город" + 0.258*"музей" + -0.200*"место" + 0.179*"пражский" + 0.155*"еврейский" + -0.150*"столица" + 0.139*"мост" + 0.137*"святой" + 0.135*"храм" -0.634*"место" + -0.258*"дом" + 0.247*"располагать" + 0.205*"чешский" + 0.200*"мост" + 0.167*"город" + 0.164*"являться" + 0.151*"площадь" + -0.135*"находиться" + 0.134*"старый" -0.408*"дом" + -0.357*"святой" + 0.354*"век" + -0.267*"город" + 0.231*"площадь" + -0.196*"улица" + -0.187*"собор" + -0.167*"старый" + 0.136*"место" + -0.129*"располагать" -0.369*"чешский" + 0.351*"город" + -0.248*"место" + 0.246*"дом" + -0.202*"еврейский" + -0.200*"храм" + -0.189*"располагать" + -0.175*"кладбище" + 0.164*"век" + -0.163*"район
Это тоже самое, но машинно с шумом. Огрехи парсинга. Пассажи. Пассажи - важно: би-три-граммы, lsi/lda модели оттуда. Тут есть еще проблемы. А так ручками 1000 - или 20-сколько есть лимитов не суть. Пассажи необработанные во вложении, на 00:41
Шум это у меня, а не когда ручками корпус сделать. Когда ручками, исключаются 2 типа ошибок:
1. не возьмешь этот урл
2. аккуратно выберешь контент (хотя не уверен, что это ошибка. Яндекс то тоже это видит)
Ну да, как уже говорил, странные штучки дает 2гис, вк а так же, наверное, то что называлось спектр, что намекнули н-граммы (я их реже глазами смотрел, а там "disk_djujmovyj_legkosplavnyj_steppe", 97], ["bachok_bol'shoj_ob'em_omyvatel'", 84) видимо запчасти какие то зашли
файл во вложении снят сейчас. Нет проблем их писать. Выше приведенные данные могут отличаться по источникам
чуть торможу, не успеваю, осмысливаю.
-------
если по смыслу
то 2гис чаще всего нормальные данные дает, но осмыслить это может только человек. Ну, типа "Рога и копыта", если чел посмотрит, сразу скажет, так ё, они розовых слонов продают в моем городе, а я как раз их и искал.
Вообще все н-граммы юзаются до 4
[["disk_djujmovyj_legkosplavnyj_steppe", 97], ["bachok_bol'shoj_ob'em_omyvatel'", 84], ["kozyrek_solntsezaschitnyj_vstraivat'_zerkalo", 81], ["esp_kursovoj_sistema_stabilizatsija", 73]
Другой вопрос, что в задаче надо
а тут
["kaptur_kupit'_renault", 20]
а запрос повторю "renault kaptur купить"
Циферка кол - во найденных н-грамм. kaptur_kupit'_renault это все сочетания слов kaptur kupit' и renault
В том числе, для определения значимости и заморочился.
Если в лоб, по кол-ву вхождений, то для "renault kaptur купить", на корпусе - контент документов из 20:
[["chernyj tsvet", 191], ["bezopasnost' podushka", 181], ["zadnij zerkalo", 170], ["kaptur vnedorozhnik", 163], ["perednij zadnij", 149], ["kaptur renault", 148], ["djujmovyj legkosplavnyj", 142], ["bezopasnost' perednij", 140], ["perednij voditel'", 137], ["naruzhnyj zerkalo", 131], ["avto ostavat'sja", 114], ["vid zadnij", 103], ["hromirovannyj nakladka", 97], ["slonovyj tsvet", 94]...
Если по одному, то часто вообще непредсказуемо получается, типа как "avto ostavat'sja" несколько первых
* биграммы сортированы, в "kaptur renault" включен "renault kaptur".
Что касается, когда есть запрос и надо расширить, еще используется
[["kaptur renault", 125], ["disk renault", 4], ["renault vozduhovod", 4], ["diler ofitsial'nyj", 3], ["nakladka porog", 3], ["moskva ofitsial'nyj", 2], ["deflektor vozduhovod", 2], ["nizhnij novgorod", 2], ["porog renault", 1]] ... 0.220*"renault" + 0.220*"купить" + 0.220*"kaptur" + 0.027*"официальный" + 0.027*"самара" + 0.027*"дилер" + 0.027*"москва" + 0.014*"дон" + 0.014*"новгород" + 0.014*"ижевск" ...
анализ ключевиков в качестве данных для окончательной сборки запроса на поиск обвеса.
Смысл схож, но неясно какой алгоритм и какой текстовый корпус используется для построения списка.
Судя по
том случае 0.298
не делают
words = mystem.lemmatize(text) #.... words = [t for t in words if t not in ru_stopwords]
Да, копирайтинг в данном контексте точно не рассматриваю. Задача возникла в результате разработки портала/доски/агрегатора/отраслевых новостей. Как задача автоматического определения ключевых фраз для товарного предложения/листинга и обвеса документа различным доп. контентом максимально раскрывающую тему документа.
Например, есть объявление (только в качестве примера). Используя данные (это не все):
$ /home/web/py/w2v/corpus<class 'gensim.models.ldamodel.LdaModel'> num_topics=40.043*"битый" + 0.042*"renault" + 0.042*"привод" + 0.042*"состояние" + 0.042*"купить" + 0.042*"полный" + 0.041*"kaptur" + 0.024*"комплект" + 0.024*"проверка" + 0.024*"красить"0.075*"тип" + 0.075*"двигатель" + 0.042*"внедорожник" + 0.042*"renault" + 0.042*"бензин" + 0.042*"кузов" + 0.042*"выпуск" + 0.042*"марка" + 0.041*"год" + 0.041*"объем"0.055*"kaptur" + 0.051*"челябинский" + 0.051*"область" + 0.032*"renault" + 0.032*"купить" + 0.031*"комплектация" + 0.029*"avito" + 0.029*"салон" + 0.029*"перекуп" + 0.029*"торг"0.039*"проверка" + 0.039*"запуск" + 0.039*"машина" + 0.039*"доступ" + 0.039*"система" + 0.039*"сигнализация" + 0.039*"готовый" + 0.039*"бесключевой" + 0.039*"авто" + 0.038*"руль"<class 'gensim.models.lsimodel.LsiModel'> num_topics=40.365*"renault" + 0.365*"kaptur" + 0.343*"купить" + 0.238*"двигатель" + 0.235*"полный" + 0.235*"привод" + 0.233*"машина" + 0.222*"состояние" + 0.222*"год" + 0.222*"комплектация"0.433*"проверка" + 0.261*"авто" + 0.261*"система" + 0.261*"запуск" + 0.261*"доступ" + 0.261*"готовый" + 0.261*"сигнализация" + 0.261*"бесключевой" + 0.259*"машина" + 0.194*"битый"0.434*"челябинский" + 0.434*"область" + 0.256*"осмотр" + 0.256*"квартал" + 0.256*"машгородок" + 0.256*"место" + 0.256*"миасс" + 0.178*"avito" + 0.156*"renault" + 0.156*"kaptur"-0.349*"битый" + -0.292*"кредит" + -0.292*"залог" + -0.292*"проходить" + -0.292*"резина" + -0.292*"комплект" + -0.292*"красить" + 0.205*"авто" + 0.205*"система" + 0.205*"запуск"=summarize=word_count=20=Renault Kaptur, 2018 купить. Renault Kaptur, 2018 купить в Челябинской области на Avito. Тип двигателя: бензин. Renault Kaptur в отличном состоянии, машина на гарантии.=bigram=gensim.models.phrases.Phrases(dataset, min_count=1, threshold=1, delimiter=b' ')['renault kaptur', 'купить']['renault kaptur', 'купить', 'челябинский область', 'avito']['марка', 'renault']['модель', 'kaptur']['поколение']['модификация', 'mt']['год', 'выпуск']['пробег', 'км']['состояние', 'битый']['владелец', 'птс']['тип', 'кузов', 'внедорожник']['количество', 'дверь']['тип', 'двигатель', 'бензин']['коробка', 'передача', 'механика']['привод', 'полный']['руль', 'левый']['цвет', 'серебряный']['комплектация', 'drive']['место', 'осмотр', 'челябинский область', 'миасс', 'квартал', 'машгородок']['объем', 'двигатель']['renault kaptur', 'отличный', 'состояние', 'машина', 'гарантия', 'купить', 'октябрь', 'год', 'комплектация', 'драйв', 'литровый', 'двигатель', 'полный', 'привод']['битый', 'красить', 'кредит', 'залог', 'проверка', 'проходить', 'комплект', 'резина']['сигнализация', 'авто', 'запуск', 'система', 'бесключевой', 'доступ', 'машина', 'готовый', 'проверка']['салон', 'перекуп', 'беспокоить', 'торг']
+ свои данные. Например, несложно заметить биграммы определены по этому маленькому тексту только 'renault kaptur' и 'челябинский область'. Понятно почему. Но, если применить метод к большой коллекции биграмм будет больше.
Дальше, букварикс/мутаген АПИ и ключевики для объявления подобраны. Потом, на основе lda/lsi топа - дополнительные темы для полного раскрытия темы, на основе которых сделать обвес документа. Изначально идея была такой.
Но, хотелось услышать еще идей-направлений как можно это применить. А тут - задания для копирайтеров :(
* массив биграмм, содержит нормализованные пассажи исследуемого текста.
Я анализирую, больше всего "странных" слов дает 2гис, вк и т.п. Но, экспертного корпуса построенного на "диссертациях" по теме у меня нет:) Поэтому сделано допущение, что контент 20 (не суть, пробовал разные варианты) первых документов выдачи Я можно рассматривать как экспертный корпус по теме ключевика.
тем не менее, спасибо за конструктивную критику и направления куда еще можно посмотреть:)
Это без проблем. Каждая строчка - тема, количество которых задается lsi_model = gensim.models.LsiModel(corpus=corpus, id2word=dct, num_topics=14) при построении модели
<class 'gensim.models.lsimodel.LsiModel'> 0.720*"цезарь" + 0.212*"год" + 0.207*"the" + 0.182*"caesar" + 0.130*"julius" + 0.117*"гай" + 0.115*"of" + 0.108*"помпей" + 0.107*"римский" + 0.107*"война" 0.717*"салат" + 0.208*"цезарь" + 0.203*"рецепт" + 0.183*"масло" + 0.141*"сыр" + 0.132*"соус" + 0.123*"курица" + 0.115*"оливковый" + 0.114*"куриный" + -0.112*"the" -0.300*"the" + 0.294*"цезарь" + 0.251*"помпей" + -0.216*"caesar" + -0.176*"салат" + -0.171*"julius" + -0.166*"of" + 0.156*"власть" + 0.151*"войско" + 0.133*"рим" -0.364*"конкурс" + -0.268*"нарезать" + -0.230*"вкус" + -0.184*"блюдо" + -0.170*"минута" + -0.155*"добавлять" + 0.153*"цезарь" + 0.148*"салат" + -0.129*"спецпроект" + -0.128*"масло" -0.667*"конкурс" + -0.236*"спецпроект" + -0.203*"блюдо" + 0.168*"масло" + 0.167*"нарезать" + -0.129*"мультиварка" + 0.101*"минута" + -0.100*"рецепт" + 0.096*"соль" + 0.094*"перец" 0.448*"фильм" + 0.239*"юлий" + -0.161*"войско" + -0.151*"помпей" + 0.144*"человек" + 0.130*"император" + 0.126*"римский" + 0.124*"сулла" + 0.111*"становиться" + 0.110*"полководец" 0.285*"фильм" + -0.271*"гай" + -0.222*"юлий" + 0.211*"рецепт" + -0.194*"римский" + -0.153*"масло" + 0.147*"шаг" + -0.144*"юлия" + -0.137*"конкурс" + -0.125*"становиться" 0.328*"фильм" + -0.284*"рецепт" + -0.217*"шаг" + -0.191*"соус" + 0.163*"масло" + -0.154*"гай" + 0.119*"помпей" + -0.113*"римский" + -0.113*"курица" + -0.112*"домашний" -0.292*"соус" + 0.189*"вкус" + 0.170*"салат" + -0.167*"пармезан" + 0.165*"классический" + -0.161*"ложка" + 0.155*"блюдо" + 0.152*"простой" + 0.146*"рецепт" + -0.146*"масло" -0.255*"юлиан" + -0.251*"август" + -0.249*"власть" + -0.230*"титул" + -0.148*"правитель" + 0.146*"помпей" + 0.145*"гай" + -0.143*"констанция" + -0.140*"император" + -0.128*"галл" 0.305*"ложка" + -0.208*"шаг" + 0.151*"курица" + -0.144*"сыр" + 0.141*"чайный" + -0.137*"соус" + 0.133*"столовый" + -0.118*"соль" + 0.118*"нарезать" + 0.117*"добавлять" 0.196*"гай" + -0.176*"год" + -0.167*"цезарь" + 0.165*"салат" + 0.139*"юлия" + 0.131*"принимать" + -0.131*"становиться" + 0.107*"фильм" + -0.107*"великий" + -0.107*"однако" -0.217*"римский" + 0.185*"гай" + -0.164*"война" + -0.153*"император" + 0.153*"принимать" + 0.123*"политик" + 0.101*"становиться" + -0.098*"юлий" + -0.096*"войско" + -0.096*"однако" -0.157*"должность" + -0.157*"республика" + -0.151*"theperson" + -0.132*"империя" + -0.124*"год" + -0.115*"провинция" + -0.115*"римский" + -0.112*"биография" + -0.109*"правление" + -0.109*"деятель" <class 'gensim.models.lsimodel.LsiModel'> 0.715*"наполеон" + 0.426*"год" + 0.146*"армия" + 0.143*"франция" + 0.139*"французский" + 0.110*"бонапарт" + 0.086*"становиться" + 0.083*"войско" + 0.080*"военный" + 0.078*"император" -0.525*"торт" + -0.286*"мука" + -0.269*"рецепт" + -0.239*"сахар" + -0.228*"наполеон" + -0.223*"масло" + -0.213*"молоко" + -0.211*"сливочный" + 0.193*"год" + -0.184*"крем" 0.360*"год" + -0.327*"бонапарт" + -0.299*"франция" + -0.219*"император" + -0.147*"французский" + 0.118*"тыс" + 0.115*"май" + -0.110*"фильм" + -0.106*"становиться" + -0.104*"генерал" 0.296*"наполеон" + 0.261*"фильм" + -0.241*"год" + -0.213*"франция" + 0.209*"конкурс" + 0.149*"человек" + 0.144*"клавье" + -0.144*"мука" + -0.121*"сахар" + -0.111*"молоко" -0.657*"конкурс" + -0.233*"спецпроект" + -0.222*"блюдо" + -0.200*"рецепт" + 0.130*"наполеон" + -0.127*"мультиварка" + -0.126*"год" + 0.125*"мука" + -0.122*"торт" + 0.114*"сахар" 0.520*"бонапарт" + 0.252*"год" + 0.218*"император" + 0.136*"биография" + -0.115*"наполеон" + -0.115*"франция" + 0.113*"становиться" + -0.109*"фильм" + -0.103*"армия" + -0.087*"империя" 0.369*"год" + 0.324*"фильм" + -0.224*"наполеон" + 0.179*"клавье" + 0.143*"человек" + 0.119*"исторический" + 0.116*"история" + 0.110*"сериал" + 0.109*"роль" + -0.099*"англия" -0.306*"конкурс" + 0.296*"торт" + -0.247*"мука" + 0.235*"приготавливать" + -0.230*"сахар" + -0.209*"сливочный" + -0.205*"масло" + -0.201*"молоко" + 0.172*"рецепт" + 0.166*"слоеный" 0.180*"битва" + -0.161*"the" + -0.154*"кавалер" + -0.151*"орден" + -0.130*"and" + -0.119*"of" + -0.107*"время" + -0.103*"император" + -0.097*"википедия" + -0.096*"буонапарт" 0.188*"французский" + -0.186*"биография" + -0.149*"становиться" + -0.146*"военный" + -0.145*"страна" + -0.136*"жозефина" + -0.125*"париж" + 0.124*"наполеон" + -0.118*"император" + 0.114*"республика" 0.285*"французский" + 0.167*"век" + 0.146*"деятель" + 0.144*"государственный" + -0.118*"большой" + 0.109*"война" + -0.106*"бонапарт" + -0.105*"кавалер" + -0.102*"получать" + 0.101*"наполеоновский" 0.300*"биография" + -0.169*"франция" + 0.152*"интересный" + -0.144*"год" + 0.133*"краткий" + 0.122*"деятельность" + 0.112*"поход" + 0.111*"факт" + 0.109*"бежать" + 0.107*"жена" 0.138*"полководец" + 0.127*"биография" + 0.122*"интересный" + 0.118*"факт" + 0.110*"однако" + 0.109*"являться" + 0.108*"француз" + 0.107*"результат" + -0.097*"карьера" + -0.094*"жена" 0.191*"краткий" + 0.190*"полководец" + 0.187*"великий" + 0.169*"армия" + 0.132*"союзный" + -0.126*"однако" + 0.122*"отступать" + 0.113*"сражение" + 0.109*"нужный" + 0.099*"карта" 0.231*"карта" + 0.197*"подарочный" + 0.197*"рубль" + 0.197*"книжный" + 0.197*"магазин" + 0.166*"класс" + 0.164*"ребенок" + 0.156*"биография" + -0.154*"великий" + 0.145*"получать"
цезарь салат
Аналогичного мнения
Не всегда одинаково:(
Все больше и больше Python приходится использовать.
Предугадать, что там понадобится за время жизни проекта сложно, но учитывая наличие большого количества библиотек Python на все случаи жизни, рекомендовал бы Python в качестве одного из инструментов.
Поясню на своем примере. Понадобилось всякую аналитику по запросам иметь, лучшее что нашел Gensim, что потянуло за собой - парсер я-хмл, сайтов на php, аналитика - Gensim на Python. Много сущностей. Проще все это иметь на одной технологии. Оказалось все даже проще и лучше чем на PHP.
import requests, bs4 #а если не хватает: from selenium import webdriver
просто и элегантно решили проблему парсинга