В последнее время много сообщений о всяческих чекерах, сканерах и прочих программах, которые проверяют… ну, допустим доступность никнейма для регистрации на сервисе. Ведь если на сервисе никнейм не доступен, это значит, что нужно будет постараться и придумать другой. Я нашел три таких веб-сервиса, где можно в ручном режиме проверить доступность ника. Количество сервисов у них разное, сервисы опять же разные, а потому проверять лучше на всех трех.
Ну я и подумал, а почему бы мне не сделать скриптик, который сам бы запрашивал данные у сервисов и возвращал бы мне уже готовый результат. Чтобы не было необходимости открывать сервисы, ждать пока все прогрузиться. Автоматизировать данный процесс. То есть парсить сервисы, чтобы получить их данные парсинга сервисов. Такое вот масло масляное. )) В общем, подумал и начал посмотреть, как это можно сделать. Здесь у нас есть два путя, как в анекдоте, а точнее, для меня доступных – три.
Первый путь – это делать простые запросы к странице сервисов. Но, этот путь уже изначально тупиковый. Так как сервисы динамические и потому данных мы не получим, а получим голый html-код, возможно со скриптами.
Второй путь – это использовать selenium. В принципе, годный путь. Особенно если скрыть браузер и выполнять запросы в тихом режиме. Так можно получить код страницы уже с данными и оттуда выдернуть все, что нужно, но этот путь тоже не подходит, так как он будет достаточно медленный. А именно будет затрачиваться время на сканирование ресурсов самим сервисом, плюс время на поиск данных.
Третий путь – поискать запросы, которые сервис отправляет на сканирование ресурсов и попытаться эти запросы использовать в своем скрипте на питоне. Это был бы предпочтительный путь, так как тут сократиться время на ввод данных.
В общем после того, как я посмотрел на сервисы, поискал в запросах, было уже совершенно очевидно, что будет использоваться третий путь. Это как раз тот случай, когда третьего дано.
Идем на сервисы и смотрим, что улетает и прилетает при отправке нами запроса. Или вводе никнейма, как на одном из сервисов. Открываем инструменты разработчика, которые открываются при щелчке правой кнопкой мыши по странице и выборе пункта меню «Исследовать элемент». И уже тут переходим на вкладку «Сеть» или «Network» у кого не русифицированная версия. Выставляем фильтр запросов в «Fetch/XHR» или просто «XHR». Тут уже зависит от версии браузера. И делаем запрос на поиск никнейма.
Сервисов тут не особо много и к каждому из них отправляется запрос на сканирование. Результат сканирования возвращается в виде JSON, в котором в ключе «available» указывается доступность регистрации. Если доступность false, значит такой никнейм уже существует. Если true, значит такого ника на сайте нет и можно регистрироваться. Открываем запрос в новой вкладке и видим, что данные прилетают в открытом виде. А сам запрос отправляет название соцсети в ссылке.
Потому, нужно будет пройтись по всем запросам и посмотреть, как именно называется соцсеть в данном случае, чтобы составить список, по которому и будут делаться запросы на данном сервисе. Вот что у меня получилось:
Сервисов тут немного, но, тем не менее есть такие, которые не встречаются у других. А значит, забираем все. В теории, можно было бы исключить из списка те сервисы, запросы к которым делаются на других сайтах. Но, мне было просто лень сравнивать результаты вручную. Да и писать для этого костыль на питоне тоже. А потому, я просто сделал проверку перед добавлением результата запроса в словарь. Если такой сервис есть, то, просто не добавляем. Нет, добро пожаловать.
Теперь щелкаем по запросу правой кнопкой мыши и выбираем пункт меню «Copy -> Copy as cURL (bash)». И идем на сайт, который переводит post или get запросы из вида cURL в вид на языке программирования: curlconverter.com. Вставляем запрос и получаем код, который копируем. Тут, можно было бы этого не делать. Так как запрос в данном случае get и можно было бы просто использовать ссылку. Но, я сделал именно так потому, что тех параметров заголовков, а именно user-agent и accept оказалось недостаточно. Тогда я решил, что лучше будет забрать их все и уже методом научного тыка, а именно исключения оставить именно те, которые нужны.
Вот, что у меня получилось в итоге из той кучи, что улетает в запросе:
Ну, а теперь приступим к ваянию кода.
Что понадобиться?
Установить библиотеку requests для отправки запросов. Делается это с помощью pip и команды в терминале:
Все остальные библиотеки, используемые в коде, входят в стандартную поставку питона.
Так как сервисов у нас три, то под каждый лучше всего сделать отдельную функцию. Ведь у каждого сервиса будут свои ссылки, заголовки и параметры. Потому, создаем функцию serv_instantusername(servis, username), в которую будем отправлять имя сервиса для запроса, а так же имя пользователя.
Выполняем запрос, получаем в ответ json и делаем в нем поиск параметра available. Если он False, то забираем себе. Тут же проверяем, есть ли данный параметр в словаре. Если нет, добавляем. Ну и обернем все это в блок try – except, чтобы программа не вылетала. Так как некоторые сайты из запросов бывают просто недоступны, тогда в json прилетает ерунда и понятное дело, так как ерунду распарсить не получается, благополучно выпадает в осадок. А так, просто пропускает и двигается дальше.
Идем на второй сервис, повторяем те же действия, что и на первом. Здесь видим ту же картину. К каждому сайту делается отдельный запрос. Но, при попытке открыть в новой вкладке запрос получаем ошибку. Ладно, это не критично. Копируем содержимое запроса «Copy -> Copy as cURL (bash)» и идем на сайт для получения питоновского кода. Здесь надо смотреть, какой тип запроса. Post или Get, чтобы получить на выходе корректные результаты. В данном случае – post. Забираем полученный код себе.
Здесь мы видим, что отправляется так же куча заголовков и словарик с параметрами. Но, тут в качестве параметра соцсети указана просто цифра, которая чему-то и соответствует.
Но в данном случае это не особо важно, так как в ответе прилетает название сервиса, а значит, его можно будет просто добавлять в словарь. А запросы выполнять в цикле с диапазоном. А вот тут мне пришлось посчитать, сколько сервисов доступно для проверки. Как оказалось – 52. То есть и цикл будет от 0 до 52.
Ну, а после пришлось слегка почистить заголовки. Так как лишнего улетало в запросе тоже много. Делаем для сервиса отдельную функцию serv_checkuser_org(serv_num, username), которая на входе получает номер для запроса и имя пользователя. И вот, что в итоге у меня получилось.
Как видите, все по той же схеме, что и в предыдущей функции. Отправляем запрос, получаем ответ. Проверяем ключ. В данном случае это ключ 'message', у которого, если он доступен для регистрации должен быть параметр exists. После делаем проверку, есть ли данный сервис у нас в словаре. Ведь одной функцией мы уже прошлись. Да и так, на всякий случае. И, если нет, добавляем. Тут так же блок try – except для того, чтобы пропускать сервисы, а не вываливаться с ошибкой. Так как тут тоже есть проблемы с доступностью.
И можно переходить к третьему сервису namecheckup. Тут алгоритм действий такой же, как и в предыдущих случаях. Точно так же здесь на каждый сервис свой запрос. Но, вот тут меня ждала небольшая засада. Ответ на запрос приходил без ссылки на страницу пользователя. А это нужно, хотя бы для того, что у многих сервисов доступ к странице вроде бы открыт, но не в особо явном виде. То есть, ввести что-то вроде: имя сервиса/имя пользователя и перейти на страницу не всегда получается. И тут мне пришлось поработать ручками. Мало того, что я составил словарь для сканирования из сервисов, так еще и к каждому сервису мне пришлось вручную добавлять ссылку на страницу пользователя. Может быть, кстати, где-то и ошибся. Прошу прощения заранее. Бывает.
А в остальном, все то же самое. Получаем, ищем – добавляем. Создадим функцию serv_checkuser_org(serv_num, username), куда на входе подаются имя сервиса и имя пользователя.
Итак, нужные функции у нас есть, что делать дальше? Если выполнять перебор по списку сервисов и ждать, пока провериться весь список, будет очень долго. Поэтому, я решил, что лучше будет использовать потоки. К сожалению, моему, конечно же, асинхронность я пока не умею. Но, буду учиться. Это дело наживное. А пока, будем пользоваться тем, что есть.
Создадим функцию thread_func_category(username), которая на входе будет получать имя пользователя. В этой функции и будут запускаться потоки. Но, тут есть один нюансик. Так как набор данных для отправки запросов все же разный, нужна будет не один цикл с потоками, а целых три. Запускать все и сразу конечно же не будем. А пройдемся по очереди по каждому сервису. То есть, запускаем цикл, в котором делаем перебор значений и по каждому значению запускаем отдельный поток. Потом ждем, когда все потоки завершать работу после сканирования первого списка и запускаем новый цикл с потоками уже для второго. Ну и с третьим точно так же. В целом, скорость увеличилась в разы.
Я тестировал до этого функции по отдельности. Но такой скорости мне получить не удавалось. Так что, использование потоков в данном случае вполне оправдано и дает увеличение скорости получения данных. Что, собственно, нам и надо.
То, что функция получилась достаточно большой – не пугайтесь. Просто здесь добавлены словари, а они в коде занимают довольно много места. На самом деле, можно было бы их все сохранить в json или просто в списки подгружать по мере необходимости. Но, в данном случае этого достаточно. Если бы сервисов было больше, то так бы сделал. А так, вполне себе допустимо.
Ну и функция main(), напоследок. Здесь запрашиваем у пользователя какой никнейм он желает проверить на доступность, после чего запускаем функцию с потоками, в которую передаем никнейм, а после завершения получения данных и наполнения словаря, записываем его в json с именем пользователя. И выводим сообщение, что проверка завершена.
Что можно было бы добавить в данный код? В функцию main() – пользовательский выбор. То есть, вдруг вам понадобиться проверить больше, чем один никнейм. Тогда лучше всего, чтобы никнеймы были у вас в списке, этот список открывать, перебирать в цикле с запуском функции получения данных в потоках и сохранять на каждой итерации полученные данные по отдельному никнейму в отдельный json. Для удобства и, для большей сохранности данных. Потому как, мало ли что может произойти. А так у вас уже будет информация по части списка. Ну и если добавить сюда еще и проверку на наличие json с данными, то если запустить функцию сканирования повторно, те никнеймы, которые уже есть в сохраненном виде, проверяться не будут. Такие вот дела.
Но, в данном случае я это реализовывать не стал. Все это легко делается самостоятельно «парой» строк кода. А на этом статью можно завершить и подвести итоги проделанной работы.
Какие знания были здесь получены:
Спасибо за внимание. Надеюсь, что данная информация будет вам полезна
Ну я и подумал, а почему бы мне не сделать скриптик, который сам бы запрашивал данные у сервисов и возвращал бы мне уже готовый результат. Чтобы не было необходимости открывать сервисы, ждать пока все прогрузиться. Автоматизировать данный процесс. То есть парсить сервисы, чтобы получить их данные парсинга сервисов. Такое вот масло масляное. )) В общем, подумал и начал посмотреть, как это можно сделать. Здесь у нас есть два путя, как в анекдоте, а точнее, для меня доступных – три.
Первый путь – это делать простые запросы к странице сервисов. Но, этот путь уже изначально тупиковый. Так как сервисы динамические и потому данных мы не получим, а получим голый html-код, возможно со скриптами.
Второй путь – это использовать selenium. В принципе, годный путь. Особенно если скрыть браузер и выполнять запросы в тихом режиме. Так можно получить код страницы уже с данными и оттуда выдернуть все, что нужно, но этот путь тоже не подходит, так как он будет достаточно медленный. А именно будет затрачиваться время на сканирование ресурсов самим сервисом, плюс время на поиск данных.
Третий путь – поискать запросы, которые сервис отправляет на сканирование ресурсов и попытаться эти запросы использовать в своем скрипте на питоне. Это был бы предпочтительный путь, так как тут сократиться время на ввод данных.
В общем после того, как я посмотрел на сервисы, поискал в запросах, было уже совершенно очевидно, что будет использоваться третий путь. Это как раз тот случай, когда третьего дано.
Идем на сервисы и смотрим, что улетает и прилетает при отправке нами запроса. Или вводе никнейма, как на одном из сервисов. Открываем инструменты разработчика, которые открываются при щелчке правой кнопкой мыши по странице и выборе пункта меню «Исследовать элемент». И уже тут переходим на вкладку «Сеть» или «Network» у кого не русифицированная версия. Выставляем фильтр запросов в «Fetch/XHR» или просто «XHR». Тут уже зависит от версии браузера. И делаем запрос на поиск никнейма.
Сервисов тут не особо много и к каждому из них отправляется запрос на сканирование. Результат сканирования возвращается в виде JSON, в котором в ключе «available» указывается доступность регистрации. Если доступность false, значит такой никнейм уже существует. Если true, значит такого ника на сайте нет и можно регистрироваться. Открываем запрос в новой вкладке и видим, что данные прилетают в открытом виде. А сам запрос отправляет название соцсети в ссылке.
Потому, нужно будет пройтись по всем запросам и посмотреть, как именно называется соцсеть в данном случае, чтобы составить список, по которому и будут делаться запросы на данном сервисе. Вот что у меня получилось:
Python:
servis_instantusername = ['facebook', 'patreon', 'tiktok', 'angellist', 'hackernews', 'about.me', 'vk', '9gag',
'instagram', 'blogger', 'reddit', 'twitter', 'medium', 'goodreads', 'producthunt',
'github', 'quora', '500px', 'youtube', 'academia.edu', 'badoo', 'aptoide', 'askfm',
'blip.fm', 'bitbucket', 'bandcamp', 'basecamp', 'behance']
Сервисов тут немного, но, тем не менее есть такие, которые не встречаются у других. А значит, забираем все. В теории, можно было бы исключить из списка те сервисы, запросы к которым делаются на других сайтах. Но, мне было просто лень сравнивать результаты вручную. Да и писать для этого костыль на питоне тоже. А потому, я просто сделал проверку перед добавлением результата запроса в словарь. Если такой сервис есть, то, просто не добавляем. Нет, добро пожаловать.
Теперь щелкаем по запросу правой кнопкой мыши и выбираем пункт меню «Copy -> Copy as cURL (bash)». И идем на сайт, который переводит post или get запросы из вида cURL в вид на языке программирования: curlconverter.com. Вставляем запрос и получаем код, который копируем. Тут, можно было бы этого не делать. Так как запрос в данном случае get и можно было бы просто использовать ссылку. Но, я сделал именно так потому, что тех параметров заголовков, а именно user-agent и accept оказалось недостаточно. Тогда я решил, что лучше будет забрать их все и уже методом научного тыка, а именно исключения оставить именно те, которые нужны.
Вот, что у меня получилось в итоге из той кучи, что улетает в запросе:
Python:
headers = {
'authority': 'api.instantusername.com',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/98.0.4758.141 YaBrowser/22.3.3.852 Yowser/2.5 Safari/537.36',
'accept': '*/*',
}
Ну, а теперь приступим к ваянию кода.
Что понадобиться?
Установить библиотеку requests для отправки запросов. Делается это с помощью pip и команды в терминале:
pip install requests
Все остальные библиотеки, используемые в коде, входят в стандартную поставку питона.
Так как сервисов у нас три, то под каждый лучше всего сделать отдельную функцию. Ведь у каждого сервиса будут свои ссылки, заголовки и параметры. Потому, создаем функцию serv_instantusername(servis, username), в которую будем отправлять имя сервиса для запроса, а так же имя пользователя.
Выполняем запрос, получаем в ответ json и делаем в нем поиск параметра available. Если он False, то забираем себе. Тут же проверяем, есть ли данный параметр в словаре. Если нет, добавляем. Ну и обернем все это в блок try – except, чтобы программа не вылетала. Так как некоторые сайты из запросов бывают просто недоступны, тогда в json прилетает ерунда и понятное дело, так как ерунду распарсить не получается, благополучно выпадает в осадок. А так, просто пропускает и двигается дальше.
Python:
def serv_instantusername(servis, username):
# здесь оставляем в заголовках authority
headers = {
'authority': 'api.instantusername.com',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/98.0.4758.141 YaBrowser/22.3.3.852 Yowser/2.5 Safari/537.36',
'accept': '*/*',
}
# делаем запрос на проверку с указанным сервисом и ником
# из полученного ответа забираем сервисы, в которых уже есть
# указанные нами ник и добавляем в словарь
try:
response = requests.get(f'https://api.instantusername.com/check/{servis}/{username}', headers=headers).json()
if response['available'] == False:
if username not in user_social:
user_social[username] = dict()
if str(response['service']).lower() not in user_social[username]:
user_social[username][str(response['service']).lower()] = response['url']
except:
pass
Идем на второй сервис, повторяем те же действия, что и на первом. Здесь видим ту же картину. К каждому сайту делается отдельный запрос. Но, при попытке открыть в новой вкладке запрос получаем ошибку. Ладно, это не критично. Копируем содержимое запроса «Copy -> Copy as cURL (bash)» и идем на сайт для получения питоновского кода. Здесь надо смотреть, какой тип запроса. Post или Get, чтобы получить на выходе корректные результаты. В данном случае – post. Забираем полученный код себе.
Здесь мы видим, что отправляется так же куча заголовков и словарик с параметрами. Но, тут в качестве параметра соцсети указана просто цифра, которая чему-то и соответствует.
Python:
data = {
'index': '0',
'username': 'user',
}
Но в данном случае это не особо важно, так как в ответе прилетает название сервиса, а значит, его можно будет просто добавлять в словарь. А запросы выполнять в цикле с диапазоном. А вот тут мне пришлось посчитать, сколько сервисов доступно для проверки. Как оказалось – 52. То есть и цикл будет от 0 до 52.
Ну, а после пришлось слегка почистить заголовки. Так как лишнего улетало в запросе тоже много. Делаем для сервиса отдельную функцию serv_checkuser_org(serv_num, username), которая на входе получает номер для запроса и имя пользователя. И вот, что в итоге у меня получилось.
Python:
def serv_checkuser_org(serv_num, username):
# здесь обязательно наличие referer
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/98.0.4758.141 YaBrowser/22.3.3.852 Yowser/2.5 Safari/537.36',
'accept': '*/*',
'referer': 'https://checkuser.org/',
}
# словарик с данными, которые отправляются в запросе на проверку
# имя сервиса и никнейм
data = {
'index': serv_num,
'username': username,
}
# отправляем запрос и в ответе json ищем те сервисы
# на которых регистрация недоступна
# это и будут искомые нами сервисы с никнеймом
try:
response = requests.post('https://checkuser.org/existence.php', headers=headers, data=data).json()
if response['message'] == 'exists':
if username not in user_social:
user_social[username] = dict()
if str(response['domain']).split(".")[0].lower() not in user_social[username]:
user_social[username][str(response['domain']).split(".")[0].lower()] = response['url']
except:
pass
Как видите, все по той же схеме, что и в предыдущей функции. Отправляем запрос, получаем ответ. Проверяем ключ. В данном случае это ключ 'message', у которого, если он доступен для регистрации должен быть параметр exists. После делаем проверку, есть ли данный сервис у нас в словаре. Ведь одной функцией мы уже прошлись. Да и так, на всякий случае. И, если нет, добавляем. Тут так же блок try – except для того, чтобы пропускать сервисы, а не вываливаться с ошибкой. Так как тут тоже есть проблемы с доступностью.
И можно переходить к третьему сервису namecheckup. Тут алгоритм действий такой же, как и в предыдущих случаях. Точно так же здесь на каждый сервис свой запрос. Но, вот тут меня ждала небольшая засада. Ответ на запрос приходил без ссылки на страницу пользователя. А это нужно, хотя бы для того, что у многих сервисов доступ к странице вроде бы открыт, но не в особо явном виде. То есть, ввести что-то вроде: имя сервиса/имя пользователя и перейти на страницу не всегда получается. И тут мне пришлось поработать ручками. Мало того, что я составил словарь для сканирования из сервисов, так еще и к каждому сервису мне пришлось вручную добавлять ссылку на страницу пользователя. Может быть, кстати, где-то и ошибся. Прошу прощения заранее. Бывает.
А в остальном, все то же самое. Получаем, ищем – добавляем. Создадим функцию serv_checkuser_org(serv_num, username), куда на входе подаются имя сервиса и имя пользователя.
Python:
def serv_checkuser_org(serv_num, username):
# здесь обязательно наличие referer
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/98.0.4758.141 YaBrowser/22.3.3.852 Yowser/2.5 Safari/537.36',
'accept': '*/*',
'referer': 'https://checkuser.org/',
}
# словарик с данными, которые отправляются в запросе на проверку
# имя сервиса и никнейм
data = {
'index': serv_num,
'username': username,
}
# отправляем запрос и в ответе json ищем те сервисы
# на которых регистрация недоступна
# это и будут искомые нами сервисы с никнеймом
try:
response = requests.post('https://checkuser.org/existence.php', headers=headers, data=data).json()
if response['message'] == 'exists':
if username not in user_social:
user_social[username] = dict()
if str(response['domain']).split(".")[0].lower() not in user_social[username]:
user_social[username][str(response['domain']).split(".")[0].lower()] = response['url']
except:
pass
Итак, нужные функции у нас есть, что делать дальше? Если выполнять перебор по списку сервисов и ждать, пока провериться весь список, будет очень долго. Поэтому, я решил, что лучше будет использовать потоки. К сожалению, моему, конечно же, асинхронность я пока не умею. Но, буду учиться. Это дело наживное. А пока, будем пользоваться тем, что есть.
Создадим функцию thread_func_category(username), которая на входе будет получать имя пользователя. В этой функции и будут запускаться потоки. Но, тут есть один нюансик. Так как набор данных для отправки запросов все же разный, нужна будет не один цикл с потоками, а целых три. Запускать все и сразу конечно же не будем. А пройдемся по очереди по каждому сервису. То есть, запускаем цикл, в котором делаем перебор значений и по каждому значению запускаем отдельный поток. Потом ждем, когда все потоки завершать работу после сканирования первого списка и запускаем новый цикл с потоками уже для второго. Ну и с третьим точно так же. В целом, скорость увеличилась в разы.
Я тестировал до этого функции по отдельности. Но такой скорости мне получить не удавалось. Так что, использование потоков в данном случае вполне оправдано и дает увеличение скорости получения данных. Что, собственно, нам и надо.
То, что функция получилась достаточно большой – не пугайтесь. Просто здесь добавлены словари, а они в коде занимают довольно много места. На самом деле, можно было бы их все сохранить в json или просто в списки подгружать по мере необходимости. Но, в данном случае этого достаточно. Если бы сервисов было больше, то так бы сделал. А так, вполне себе допустимо.
Python:
def thread_func_category(username):
# создаем словарь с вервисами для namecheckup
# к сожалению ссылки к странице с профилем он не возвращает
# потому пришлось потрудиться ручками, да и список сервисов
# все равно надо было забирать
service_namecheckup = {
'facebook': f'https://www.facebook.com/{username}',
'youtube': f'https://www.youtube.com/{username}',
'tiktok': f'https://www.tiktok.com/@{username}',
'twitter': f'https://twitter.com/{username}',
'pinterest': f'https://www.pinterest.ru/{username}',
'medium': f'https://medium.com/@{username}',
'twitch': f'https://www.twitch.tv/{username}',
'tumblr': f'https://{username}.tumblr.com/',
'github': f'https://github.com/{username}',
'disqus': f'https://disqus.com/by/{username}',
'aboutme': f'https://about.me/{username}',
'meetup': f'https://www.meetup.com/{username}',
'periscope': f'https://www.pscp.tv/{username}',
'patreon': f'https://www.patreon.com/{username}/creators',
'behance': f'https://www.behance.net/{username}',
'livejournal': f'https://{username}.livejournal.com/',
'buzzfeed': f'https://www.buzzfeed.com/{username}',
'vk': f'https://vk.com/{username}',
'blogger': f'https://{username}.blogspot.com',
'wordpress': f'https://{username}.wordpress.com/',
'spotify': f'https://open.spotify.com/user/{username}',
'gravatar': f'https://gravatar.com/{username}',
'bitbucket': f'https://bitbucket.org/{username}',
'id99designs': f'https://99designs.com/profiles/{username}',
'ifttt': f'https://ifttt.com/p/{username}',
'slideshare': f'https://www.slideshare.net/{username}',
'deviantart': f'https://www.deviantart.com/{username}',
'cnet': f'https://www.cnet.com/profiles/{username}',
'shopify': f'https://{username}.myshopify.com/',
'askfm': f'https://ask.fm/{username}',
'soundcloud': f'https://soundcloud.com/{username}',
'etsy': f'https://www.etsy.com/people/{username}',
'shutterstock': f'https://www.shutterstock.com/ru/g/{username}/about',
'okru': f'https://ok.ru/{username}',
'lastfm': f'https://www.last.fm/user/{username}',
'vimeo': f'https://vimeo.com/{username}',
'dribble': f'https://dribbble.com/{username}/about',
'myspace': f'https://myspace.com/{username}',
'slack': f'https://{username}.slack.com/',
'quora': f'https://www.quora.com/profile/{username}',
'wikipedia': f'https://en.wikipedia.org/wiki/User:{username}',
'dailymotion': f'https://www.dailymotion.com/{username}',
'goodreads': f'https://www.goodreads.com/user/show/{username}',
'indiegogo': f'https://www.indiegogo.com/projects/{username}',
'taskrabbit': f'https://www.taskrabbit.com/profile/{username}',
'devto': f'https://dev.to/{username}',
'id9gag': f'https://9gag.com/u/{username}',
'houzz': f'https://www.houzz.ru/user/{username}',
'gitlab': f'https://gitlab.com/{username}',
'mastodon': f'https://mastodon.social/@{username}',
'imageshack': f'https://imageshack.com/user/{username}',
'steamcommunity': f'https://steamcommunity.com/id/{username}',
'hackernoon': f'https://hackernoon.com/{username}',
'wikihow': f'https://www.wikihow.com/{username}',
'discord': f'https://discord.io/{username}',
'telegram': f'https://telegram.me/{username}',
'ebay': f'https://www.ebay.com/usr/{username}',
'producthunt': f'https://www.producthunt.com/@{username}',
'donationalerts': f'https://www.donationalerts.com/{username}',
'linktree': f'https://linktr.ee/{username}',
'photobucket': f'https://app.photobucket.com/u/{username}',
'roblox': f'http://www.roblox.com/{username}',
'ign': f'https://www.ign.com/person/{username}',
'basecamp': f'https://basecamp.com/{username}',
'quizlet': f'https://quizlet.com/{username}',
'genius': f'https://genius.com/{username}',
'steemit': f'https://steemit.com/@{username}',
'fandom': f'https://www.fandom.com/{username}'
}
# список сервисов для instantusername
# тут сервисов поменьше, а в ответе возвращается ссылка на профиль
servis_instantusername = ['facebook', 'patreon', 'tiktok', 'angellist', 'hackernews', 'about.me', 'vk', '9gag',
'instagram', 'blogger', 'reddit', 'twitter', 'medium', 'goodreads', 'producthunt',
'github', 'quora', '500px', 'youtube', 'academia.edu', 'badoo', 'aptoide', 'askfm',
'blip.fm', 'bitbucket', 'bandcamp', 'basecamp', 'behance']
# делаем принт с информированием о запуске запросов, чтобы не было скучно
# запускаем в цикле потоки для проверки первого сервиса
# затем проверяем количество работающих потоков, чтобы все заврешились
print('[+] Проверка первого сервиса...')
for service in service_namecheckup:
t = threading.Thread(target=serv_namecheckup, kwargs={'service': service, 'username': username,
'url': service_namecheckup[service]})
t.start()
threadslist = int(threading.active_count())
while threadslist > 1:
threadslist = int(threading.active_count())
time.sleep(0.000001)
# принт для того, чтобы было нескучно о сканировании второго сервиса
# запускаем потоки в цикле перебора сервисов в списке instantusername
# ждем, пока потоки завершаться
print('[+] Проверка второго сервиса...')
for servis in servis_instantusername:
t = threading.Thread(target=serv_instantusername, kwargs={'servis': servis, 'username': username})
t.start()
threadslist = int(threading.active_count())
while threadslist > 1:
threadslist = int(threading.active_count())
time.sleep(0.000001)
# запускаем принт о проверке для того, чтобы не было скучно
# в цикле до 51 запускаем потоки
# для сервиса checkuser.org список сервисов не нужен
# здесь запросы идут по цифрам, каждая из которых соответствует
# определенному сервису, после чего ждем, пока завершаться потоки
print('[+] Проверка третьего сервиса...')
for serv_num in range(0, 52):
t = threading.Thread(target=serv_checkuser_org, kwargs={'serv_num': serv_num, 'username': username})
t.start()
threadslist = int(threading.active_count())
while threadslist > 1:
threadslist = int(threading.active_count())
time.sleep(0.000001)
Ну и функция main(), напоследок. Здесь запрашиваем у пользователя какой никнейм он желает проверить на доступность, после чего запускаем функцию с потоками, в которую передаем никнейм, а после завершения получения данных и наполнения словаря, записываем его в json с именем пользователя. И выводим сообщение, что проверка завершена.
Python:
def main():
username = input('[+] Введите логин для проверки: ').lower()
thread_func_category(username)
with open(f'result_{username}.json', 'w', encoding='utf-8') as file:
json.dump(user_social, file, indent=4, ensure_ascii=False)
print('[+] Проверка завершена. Данные сохранены...')
Что можно было бы добавить в данный код? В функцию main() – пользовательский выбор. То есть, вдруг вам понадобиться проверить больше, чем один никнейм. Тогда лучше всего, чтобы никнеймы были у вас в списке, этот список открывать, перебирать в цикле с запуском функции получения данных в потоках и сохранять на каждой итерации полученные данные по отдельному никнейму в отдельный json. Для удобства и, для большей сохранности данных. Потому как, мало ли что может произойти. А так у вас уже будет информация по части списка. Ну и если добавить сюда еще и проверку на наличие json с данными, то если запустить функцию сканирования повторно, те никнеймы, которые уже есть в сохраненном виде, проверяться не будут. Такие вот дела.
Но, в данном случае я это реализовывать не стал. Все это легко делается самостоятельно «парой» строк кода. А на этом статью можно завершить и подвести итоги проделанной работы.
Какие знания были здесь получены:
- научились искать запросы в инструментах разработчика;
- узнали, как получать код из cURL;
- как добавлять данные в словарь;
- использовать потоки для получения данных.
Python:
"""Скрипт для получения данных от трех сервисов с проверкой никнейма
на доступность для регистрации, с использованием потоков"""
import json
import threading
import time
# pip install requests
import requests
# создаем словарик, куда будем складывать результаты
user_social = {}
# запускаем сканирование на сервисе namecheckup
def serv_namecheckup(service, username, url):
# добавляем заголовки
# тут обязательно надо оставить referer
# без него данные не прилетают
headers = {
'referrer': '/',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/98.0.4758.141 YaBrowser/22.3.3.852 Yowser/2.5 Safari/537.36',
'accept': '*/*',
}
# словарик с именем пользователя и соцсетью
data = {
'data[name]': username,
'data[media]': service,
'data[tx]': '1'
}
# делаем запрос на проверку указанной в параметрах соцсети
# и получаем ответ в json
# вытаскиваем нужные данные, а именно, недоступность для регистрации
# это и будет указывать на существование данного user name в сервисе
# добавляем в словарь
try:
response = requests.post('https://namecheckup.com/api/v1/media/check', headers=headers, data=data).json()
if response['data']['available'] == False:
if username not in user_social:
user_social[username] = dict()
if str(response['data']['media']).lower() not in user_social[username]:
user_social[username][str(response['data']['media']).lower()] = url
except:
pass
# запускаем сканирование на сервисе instantusername
def serv_instantusername(servis, username):
# здесь оставляем в заголовках authority
headers = {
'authority': 'api.instantusername.com',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/98.0.4758.141 YaBrowser/22.3.3.852 Yowser/2.5 Safari/537.36',
'accept': '*/*',
}
# делаем запрос на проверку с указанным сервисом и ником
# из полученного ответа забираем сервисы, в которых уже есть
# указанные нами ник и добавляем в словарь
try:
response = requests.get(f'https://api.instantusername.com/check/{servis}/{username}', headers=headers).json()
if response['available'] == False:
if username not in user_social:
user_social[username] = dict()
if str(response['service']).lower() not in user_social[username]:
user_social[username][str(response['service']).lower()] = response['url']
except:
pass
# запускаем сканирование на сервисе checkuser.org
def serv_checkuser_org(serv_num, username):
# здесь обязательно наличие referer
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/98.0.4758.141 YaBrowser/22.3.3.852 Yowser/2.5 Safari/537.36',
'accept': '*/*',
'referer': 'https://checkuser.org/',
}
# словарик с данными, которые отправляются в запросе на проверку
# имя сервиса и никнейм
data = {
'index': serv_num,
'username': username,
}
# отправляем запрос и в ответе json ищем те сервисы
# на которых регистрация недоступна
# это и будут искомые нами сервисы с никнеймом
try:
response = requests.post('https://checkuser.org/existence.php', headers=headers, data=data).json()
if response['message'] == 'exists':
if username not in user_social:
user_social[username] = dict()
if str(response['domain']).split(".")[0].lower() not in user_social[username]:
user_social[username][str(response['domain']).split(".")[0].lower()] = response['url']
except:
pass
# запускаем потоки для отправки запросов на сервисы
def thread_func_category(username):
# создаем словарь с вервисами для namecheckup
# к сожалению ссылки к странице с профилем он не возвращает
# потому пришлось потрудиться ручками, да и список сервисов
# все равно надо было забирать
service_namecheckup = {
'facebook': f'https://www.facebook.com/{username}',
'youtube': f'https://www.youtube.com/{username}',
'tiktok': f'https://www.tiktok.com/@{username}',
'twitter': f'https://twitter.com/{username}',
'pinterest': f'https://www.pinterest.ru/{username}',
'medium': f'https://medium.com/@{username}',
'twitch': f'https://www.twitch.tv/{username}',
'tumblr': f'https://{username}.tumblr.com/',
'github': f'https://github.com/{username}',
'disqus': f'https://disqus.com/by/{username}',
'aboutme': f'https://about.me/{username}',
'meetup': f'https://www.meetup.com/{username}',
'periscope': f'https://www.pscp.tv/{username}',
'patreon': f'https://www.patreon.com/{username}/creators',
'behance': f'https://www.behance.net/{username}',
'livejournal': f'https://{username}.livejournal.com/',
'buzzfeed': f'https://www.buzzfeed.com/{username}',
'vk': f'https://vk.com/{username}',
'blogger': f'https://{username}.blogspot.com',
'wordpress': f'https://{username}.wordpress.com/',
'spotify': f'https://open.spotify.com/user/{username}',
'gravatar': f'https://gravatar.com/{username}',
'bitbucket': f'https://bitbucket.org/{username}',
'id99designs': f'https://99designs.com/profiles/{username}',
'ifttt': f'https://ifttt.com/p/{username}',
'slideshare': f'https://www.slideshare.net/{username}',
'deviantart': f'https://www.deviantart.com/{username}',
'cnet': f'https://www.cnet.com/profiles/{username}',
'shopify': f'https://{username}.myshopify.com/',
'askfm': f'https://ask.fm/{username}',
'soundcloud': f'https://soundcloud.com/{username}',
'etsy': f'https://www.etsy.com/people/{username}',
'shutterstock': f'https://www.shutterstock.com/ru/g/{username}/about',
'okru': f'https://ok.ru/{username}',
'lastfm': f'https://www.last.fm/user/{username}',
'vimeo': f'https://vimeo.com/{username}',
'dribble': f'https://dribbble.com/{username}/about',
'myspace': f'https://myspace.com/{username}',
'slack': f'https://{username}.slack.com/',
'quora': f'https://www.quora.com/profile/{username}',
'wikipedia': f'https://en.wikipedia.org/wiki/User:{username}',
'dailymotion': f'https://www.dailymotion.com/{username}',
'goodreads': f'https://www.goodreads.com/user/show/{username}',
'indiegogo': f'https://www.indiegogo.com/projects/{username}',
'taskrabbit': f'https://www.taskrabbit.com/profile/{username}',
'devto': f'https://dev.to/{username}',
'id9gag': f'https://9gag.com/u/{username}',
'houzz': f'https://www.houzz.ru/user/{username}',
'gitlab': f'https://gitlab.com/{username}',
'mastodon': f'https://mastodon.social/@{username}',
'imageshack': f'https://imageshack.com/user/{username}',
'steamcommunity': f'https://steamcommunity.com/id/{username}',
'hackernoon': f'https://hackernoon.com/{username}',
'wikihow': f'https://www.wikihow.com/{username}',
'discord': f'https://discord.io/{username}',
'telegram': f'https://telegram.me/{username}',
'ebay': f'https://www.ebay.com/usr/{username}',
'producthunt': f'https://www.producthunt.com/@{username}',
'donationalerts': f'https://www.donationalerts.com/{username}',
'linktree': f'https://linktr.ee/{username}',
'photobucket': f'https://app.photobucket.com/u/{username}',
'roblox': f'http://www.roblox.com/{username}',
'ign': f'https://www.ign.com/person/{username}',
'basecamp': f'https://basecamp.com/{username}',
'quizlet': f'https://quizlet.com/{username}',
'genius': f'https://genius.com/{username}',
'steemit': f'https://steemit.com/@{username}',
'fandom': f'https://www.fandom.com/{username}'
}
# список сервисов для instantusername
# тут сервисов поменьше, а в ответе возвращается ссылка на профиль
servis_instantusername = ['facebook', 'patreon', 'tiktok', 'angellist', 'hackernews', 'about.me', 'vk', '9gag',
'instagram', 'blogger', 'reddit', 'twitter', 'medium', 'goodreads', 'producthunt',
'github', 'quora', '500px', 'youtube', 'academia.edu', 'badoo', 'aptoide', 'askfm',
'blip.fm', 'bitbucket', 'bandcamp', 'basecamp', 'behance']
# делаем принт с информированием о запуске запросов, чтобы не было скучно
# запускаем в цикле потоки для проверки первого сервиса
# затем проверяем количество работающих потоков, чтобы все заврешились
print('[+] Проверка первого сервиса...')
for service in service_namecheckup:
t = threading.Thread(target=serv_namecheckup, kwargs={'service': service, 'username': username,
'url': service_namecheckup[service]})
t.start()
threadslist = int(threading.active_count())
while threadslist > 1:
threadslist = int(threading.active_count())
time.sleep(0.000001)
# принт для того чтобы было нескучно о сканировании второго сервиса
# запускаем потоки в цикле перебора сервисов в списке instantusername
# ждем, пока потоки завершаться
print('[+] Проверка второго сервиса...')
for servis in servis_instantusername:
t = threading.Thread(target=serv_instantusername, kwargs={'servis': servis, 'username': username})
t.start()
threadslist = int(threading.active_count())
while threadslist > 1:
threadslist = int(threading.active_count())
time.sleep(0.000001)
# запускаем принт о проверке, для того, чтобы не было скучно
# в цикле до 51 запускаем потоки
# для сервиса checkuser.org список сервисов не нужен
# здесь запросы идут по цифрам, каждая из которых соответствует
# определенному сервису, после чего ждем, пока завершаться потоки
print('[+] Проверка третьего сервиса...')
for serv_num in range(0, 52):
t = threading.Thread(target=serv_checkuser_org, kwargs={'serv_num': serv_num, 'username': username})
t.start()
threadslist = int(threading.active_count())
while threadslist > 1:
threadslist = int(threading.active_count())
time.sleep(0.000001)
# запрашиваем никнейм для проверки
# запускаем функцию для создания потоков с запросами и передаем в нее никнейм
# записываем полученный результат в файл json
def main():
username = input('[+] Введите логин для проверки: ').lower()
thread_func_category(username)
with open(f'result_{username}.json', 'w', encoding='utf-8') as file:
json.dump(user_social, file, indent=4, ensure_ascii=False)
print('[+] Проверка завершена. Данные сохранены...')
if __name__ == "__main__":
main()
Спасибо за внимание. Надеюсь, что данная информация будет вам полезна