Работа с UrlLib. Скрипт накрутки рекламы

Работа с UrlLib. Скрипт накрутки рекламы

Приветствие! Сегодня напишем программу по накручиванию рекламы, которая сможет скрывать свои реальные данные (ip, user-agent, гео-положение). Хочу заметить, что всё это исключительно в учёбных целях.

В этой статье я разберу:

UrlLib, базовая информация

Подмена user-agent

Proxy в UrlLib

Анонимизация через Tor

Выборка элементов из массива

Использование библиотеки Beautiful Soup для работы с html

Работа с DOM в Python

UrlLib

Вероятно, вы слышали о python-модуле с названием UrlLib. Он предоставляет нам высокоуровневый интерфейс для работы с World Wide Web. В возможности входит чтение информации и настройка запроса для корректной работы. Также имеются такие полезные функции, как unquote (заменяет escape-символы эквивалентами), quote (обратный аналог unquote). Существует пара базовых классов, которые предоставляют уже готовый интерфейс для работы. Всё, что нужно сделать — унаследовать их и заполнить методы нужным кодом.

Подмена user-agent

Первым шагом, для “неузнаваемости” от всяких систем слежки есть использование прокси-сервера и замена user-agent. User-agent — это часть http-запроса, которая содержит некоторую информацию о браузере, операционной системе, локальном языке. Когда-то эту информацию использовали для блокировки контента от некоторых браузеров, если они не могли отобразить его корректно (или по другим причинам). Сейчас же подделать этот параметр достаточно легко. Почитать подробней о user-agent и посмотреть примеры для самых популярных ОС и браузеров можно на википедии.

О конкретном использовании user-agent в UrlLib сможете прочитать ниже.

Использование прокси в UrlLib

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

В UrlLib задать прокси-сервера, через которые делать запросы достаточно легко. Ознакомиться с кодом можно сразу в следующей главе.

Анонимизация через Tor

Tor LogoTor — система, позволяющая устанавливать анонимное соединение. Схема работы схожа на описание прокси-серверов. Tor состоит из конечных узлов — компьютеров, через которые идёт маршрутизация траффика. Особенностью есть то, что все данные шифруются. Часто эту сеть используют хакеры, террористы и прочие, кому нужно скрыть от прослушивания какую-то информацию. Tor работает исключительно по протоколу SOCKS, поэтому для анонимизации остальных протоколов нужно использовать дополнительные инструменты. Я, например, взял Privoxy, который позволяет перенаправлять http-траффик на socks-протокол. Как настроить Tor на совместную работу с Privoxy я объяснять не буду, в интернете много информации на эту тему.

Единственное, что вам нужно знать — какие прокси сервера использовать. Для работы Tor достаточно запустить его ядро. Он автоматически использует порт 9050 для перенаправления данных и 9051 для управления настройками. Privoxy использует порт 8118.

Практическая часть. Пишем код import urllib, urllib2 proxies = {

'http' : '127.0.0.1:8118',

'ssl' : '127.0.0.1:8118',

'socks' : '127.0.0.1:9050'

} user_agent = 'Opera/9.25 (Windows NT 5.1; U; en)' page_address = 'httр://2ip. гu'

# Используем прокси + некоторые настройки proxyHandler = urllib2.ProxyHandler(proxies) pageHandler = urllib2.build_opener(proxyHandler, urllib2.HTTPHandler)

# Создаем запрос и загружаем страницу requestData = urllib2.Request(page_address, None, {'User-Agent': user_agent}) requestHandler = pageHandler. open(requestData) pageData = requestHandler. read().decode('utf-8') requestHandler. close()

Всё достаточно просто. В начале задаём параметры для запроса: user-agent, список прокси-серверов (с использованием Tor + Privoxy), адрес страницы, которую будем загружать. Последующие действия состоят из вызова нужных методов для организации запроса и его исполнения. Объяснения можно прочитать на странице UrlLib.

Как видите, предпоследней строкой мы перекодировали текст в utf-8. Теперь можно записать в файл, например: htmlFile = open('2ip_page. html', 'w') htmlFile. write(pageData) htmlFile. close()

После этого можете открыть файл 2ip_page. html и проверить ip, провайдера, user-agent. Всё это должно отличаться от вашей реальной информации!

Заметьте, что у вас должен быть включен tor-клиент и запущен privoxy-сервис!

Ура, всё это работает! Теперь все последующие запросы будут выполняться под прокси-сервером, что делает вас “анонимным”.

Выборка

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

Давайте подумаем, а что сделать, чтобы не вычислили, что вы занимаетесь плохим делом? Для начала, у компании, которая заключила с вами договор по рекламе должен быть доступ к статистике посещений сайта: количество людей, популярные браузеры, операционные системы. Первым делом я бы в завёл в скрипте список из нескольких user-agent и каждый раз выбирал бы те, которые чаще всего используются реальными посетителями на сайте.

Представьте ситуацию, на сайте у вас посещение:

Windows + Firefox — 50%

Windows + Opera — 15%

Linux + Chrome — 30%

Linux + Firefox — 5%

Заведём себе 4 строки user-agent, которые будут предоставлять данную статистику: user_agents = {

'Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11' : 50,

'Opera/9.25 (Windows NT 5.1; U; en)' : 15,

'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.1.249.1064 Safari/532.5' : 30,

'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12' : 5

}

Теперь о сути выборки: чем больше значение “ключа”, тем чаще он будет выпадать. Т. е. “Windows+Firefox” (50%) будет выпадать в 5 раз чаще, чем “Linux+Firefox” (5%).

Реализуем этот алгоритм: from random import choice user_agents = {

'Win+FF' : 50,

'Lin+Chrome' : 30,

'Win+Opera' : 15,

'Lin+FF' : 5

} c = [] for k, v in user_agents. items(): c += [k]*v print 'Win+FF: ', print sum(1 for x in range(100) if choice(c)=="Win+FF") print 'Lin+Chrome: ', print sum(1 for x in range(100) if choice(c)=="Lin+Chrome") print 'Win+Opera: ', print sum(1 for x in range(100) if choice(c)=="Win+Opera") print 'Lin+FF: ', print sum(1 for x in range(100) if choice(c)=="Lin+FF")

Для простоты я ввёл символические названия для ключей. Алгоритм довольно простой, но он достаточно медленный. Поэтому использование больших значений значительно затормозят его. Как-то позже расскажу о возможных алгоритмах выборки. После запуска скрипта я вот что получил:

Win+FF: 52

Lin+Chrome: 23

Win+Opera: 15

Lin+FF: 7

Что и требовалось доказать: элементы массива, которые имеют больше числовое значение будут выпадать чаще. Такие алгоритмы используют для вывода рекламы. Допустим, рекламодатель №1 платит в два раза больше за один показ его рекламы, чем рекламодатель №2, почему бы не показывать его рекламу в два раза чаще?

Использование библиотеки Beautiful Soup для работы с html

Продолжим работу с html. Мы получили html-контент какой-то страницы, что делать далее? Это, конечно, зависит от ваших потребностей. Вернёмся к вопросу накрутки. Конечно же, логичней будет накручивать рекламу в самых популярных постах. Я надеюсь, вы не побежали создавать массив и заполнять его вручную URL-ами. Возьмём для примера наш блог. Если посмотреть внимательней, есть раздел “популярные посты”, чтобы его вычислить, нужно посмотреть “обрамляющие” элементы. Например, div с каким-то уникальным и подходящим id.

На нашем блоге этот id = sidebartabswidget-3-section-popular. А как же теперь вытащить его содержимое? Для этого мы будем использовать прекрасную библиотеку Beautiful Soup. Когда-то я пытался решать такие проблемы регулярными выражением. Первое, что я вам скажу: парсить html регулярными выражениями плохая идея, так как есть большая вероятность того, что получишь не то, что хочешь.

Структура этого блока такая:

<div id="sidebartabswidget-3-section-popular">

<ul>

<li> <a href="post_addres"></a></li>

</ul>

</div>

Два вложенных блока (child), второй содержит атрибут href, который нам нужно собрать из каждого дочернего.

Код неоптимальный делаю, чтобы было понятней суть работы: from BeautifulSoup import BeautifulSoup soupHandler = BeautifulSoup(pageData) topicLinks = [] # Здесь будем хранить найденные ссылки for postBlock in soupHandler. findAll('div', id='sidebartabswidget-3-section-popular'): for inner in postBlock. findAll('ul'): for link in inner. findAll('a'): topicLinks. append(link['href'])

Просто, правда? Но в момент написания этого кода я парсил не блок с самыми популярными ссылками, а просто все посты подряд на главной. Я заметил особенность, что все ссылки на посты заканчиваются текстом: #more-№поста. Что же в этом случае использовать в цикле в качестве id? Ответов два: лямбда-выражение, регулярное выражение. Я опишу здесь второе: for postBlock in soupHandler. findAll('a', href=re. compile('\#more\-([0-9]*)')): topicLinks. append(postBlock['href'])

Работа с DOM в Python

Обычно рекламные блоки использую javascript для генерации контента. Т. е. вы не сможете найти в html-контенте нужную вам информацию, потому что сгенерированный код “виртуальный“, содержится в DOM страницы. Я нашёл 2 выхода из этой ситуации:

Отправка html из DOM, с помощью Ajax

Использование утилиты Selenium

Отправка html из DOM

Я вижу решение проблемы таким: используем вместо Python’a PHP + cURL. Выполняем те же действия (прокси и т. д.), подгружаем страницу, дописываем jQuery код, который отправляет Ajax-запрос скрипту. Вот псевдокод:

<?php if (!isset($_POST['dom_html']))

{

// Init cURL

// Set proxies

// Set user-agent

// Load page data

// Load JQuery

// Show page data

} else

{

$virtualHtml = $_POST['virtualHtml'];

// Profit!

}

?>

<script language="javascript">

$.post('this_script. php', { virtualHtml: $('#reclamBlock').html() });

</script>

Конечно, можно и не переписывать всё под PHP + cURL, а писать прямо в python-коде.

Selenium

Selenium LogoSelenium — достаточно мощный инструмент для тестирования web-приложений. Существует сервер (реализован на Java, мониторит localhost:4444), клиент (реализация есть под php, net, python, html, ruby), IDE (плагин к Firefox). Суть в том, что вы записываете подряд несколько команд, а они визуально вызываются из-под выбранной оболочки (firefox, chrome, opera, …).

Для примера, я вызвал Selenium IDE и записал пару действий, загрузив гугл. В итоге, получил вот такой код на выходе: from selenium import selenium import unittest, time, re class Untitled(unittest. TestCase): def setUp(self): self. verificationErrors = [] self. selenium = selenium("localhost", 4444, "*firefox", "http:/google. com/") self. selenium. start() def test_untitled(self): sel = self. selenium sel. open("/") sel. type("q", u"Да здравствует суд, самый гуманный суд в мире!") sel. wait_for_page_to_load("30000") sel. click(u"link=Кавказская пленница, или Новые приключения Шурика — Википедия") def tearDown(self): self. selenium. stop() self. assertEqual([], self. verificationErrors) if __name__ == "__main__": unittest. main()

Разберём сгенерированный код. Сначала мы создаём экземпляр клиента, указываем информацию о положении сервера и оболочке, в которой будем работать (firefox). Также не забываем указать родительский адрес (в нашем случае — google. com).

Open — существует для открытия страницы. Указываем ‘/’, т. е. путь относительно родительского адреса.

Type — ввод текста в поле с заданным id (в нашем случае ‘q’).

Wait_for_page_to_load — ожидание загрузки страницы (около 30 секунд).

Click — нажимаем по ссылке с заданным текстом.


Карта сайта


Информационный сайт Webavtocat.ru