Namecheap.com - Cheap domain name registration, renewal and transfers - Free SSL Certificates - Web Hosting

Типы данных, основные конструкции. Python.

Thursday, November 25th, 2010

Первая пачка ответов на вопросы из этого поста. Тут все элементарно, если знать немножко про функциональное программирование и ориентироваться в стандартных функциях.

1. Как получить список всех атрибутов объекта?

Очень просто, используя стандартную функцию dir. В качестве аргумента передаем тот самый объект, в данном случае (ради примера) объект string.

import string
print dir(string)
# Или так
import inspect
print [name for name,thing in inspect.getmembers(string)]

Модуль inspect предоставляет несколько очень классных методов которые позволяют собирать информацию о объектах Python.
Используя inspect можно получить содержимое класса. получить исходный код метода, выделить формат и список аргументов функции и т.д.

2. Как получить список всех публичных атрибутов объекта?

Private методы в Python начинаются с “__” поэтому все что нужно сделать чтобы получить список публичных это отфильтровать все что начинается с “__”. Тут будут очень к месту элементы функционального программирования – функция filter(f, lst) которая формирует новый список элементов последовательности – lst руководствуясь функцией f.

import sting
# так проще для понимания
def f(x):
    if x[:2] == "__":
        return False
    else:
        return True
print filter(f, [atr for atr in dir(string)])
# а это то же самое в одну строчку
print filter(lambda x : False if not cmp(x[:2], "__") else True, [atr for atr in dir(string)])

3. Как получить список методов объекта?

Используя функцию callable() которая как бы говорит реально ли вызвать объект или нет. если вызвать реально – то это метод, если нет – то свойство

print filter(lambda x : callable(getattr(string, x)), [atr for atr in dir(string)])

4. В какой “магической” переменной хранится содержимое help?

В __doc__

print string.__doc_

5. Есть два кортежа, получить третий как конкатенацию первых двух.

Элементарно.

a = (1,2)
b = (3,4)
print a + b

6. Есть два кортежа, получить третий как объединение уникальных элементов первых двух кортежей.

Сначала преобразуем конкатенацию (операция склеивания объектов линейной структуры, обычно строк) в объект – множество (элементы которого уникальны, т.е. не могут повторятся, это свойство объекта) а затем преобразуем обратно в кортеж.

a = (1,2,3)
b = (5,3,6)
print tuple(set(a + b))

7. Почему если в цикле меняется список, то используется for x in lst[:], что означает [:]?

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

a = [1,2,3,4]
print a
for i,elem in enumerate(a[:]):
    a[i] = elem * elem
print a

8. Есть два списка одинаковой длины, в одном ключи, в другом значения. Составить словарь.

Преобразуем в пары (a,1) и т.д. c помощью zip и далее преобразование в тип данных – словарь с помощью функции dict()

a = ['a','b','c']
b = [1,2,3]
print dict(zip(a,b))

9. Есть два списка разной длины, в одном ключи, в другом значения. Составить словарь. Для ключей, для которых нет значений использовать None в качестве значения. Значения, для которых нет ключей игнорировать.

Посидел, полумал, записал в одну строчку. Все просто если немножко понимать основы функционального программирования. Наверняка можно записать короче.

# можно так но тогда не выполняется 2ая часть условия. игнорирование значений для которых нет ключей.
a = ['a','b','c','d']
b = [1,2,3]
print dict(map(None, a, b))
a = ['a','b','c']
b = [1,2,3,4]
# выполняет все требования задания.
print dict(filter(lambda x : False if x is False else True, map(lambda x, y : (x, y) if x is not None else False, a, b)))

10. Есть словарь. Инвертировать его. Т.е. пары ключ: значение поменять местами — значение: ключ.

На помощь приходит метод items() который возвращает элементы словаря в виде кортежа (в виде пар) – (key, value)

a = {'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4}
print dict([(y,x) for (x,y) in a.items()])

11. Есть строка в юникоде, получить 8-битную строку в кодировке utf-8 и cp1251.

str = u'unicode sting'
print str.encode('utf-8')
print str.encode('cp1251')

12. Есть строка в кодировке cp1251, получить юникод строку.

str = 'cp1251 string'
print str.decode('cp1251')

Чтобы более детально осознать о чем идет речь :
http://docs.python.org/library/inspect.htm
http://docs.python.org/reference/datamodel.html
http://docs.python.org/tutorial/datastructures.html
http://docs.python.org/library/stdtypes.html
http://docs.python.org/library/functions.html
http://docs.python.org/howto/unicode.html

Вопросы и задания по Python.

Thursday, November 25th, 2010

Рыская по просторам интернетов, натолкнулся на “Вопросы и задания по Python”. Польза этих вопросов очевидна – подобные задания могут предлагать вам в качестве теста на человека который более менее разбирается в вопросе. + ответы на эти несложные вопросы помогут вам систематизировать свои знания.
Полностью список можно найти тут http://pyobject.ru/blog/2010/02/04/python-quiz/

Вопросы и задания по Python

  1. Типы данных, основные конструкции
  2. Функции
  3. Итераторы
  4. Модули
  5. Классы
  6. Метаклассы и дескрипторы

Кто платит Paxum?

Tuesday, November 23rd, 2010

Недавно пришла карточка Paxum, mastercard. Вообще хотелось бы что-нибудь вроде епасса, чтобы все платили в одно место, ну и вайры куда-нибудь принимать еще. Т.е. в идеале нужно 2е карты от разных систем. Я выбрал Paxum и EPESE (говорят удобно, коллеги пользуются).
спонсоры paxumОбновляемый списко тех, кто платит Paxum :
Блог
Твиттер
Paxum

На форуме master-x так же есть ветка, где присутствует русскоязычный саппорт Paxum, для многих это немаловажный фактор.

MVC модель в Python. Немного о движках шаблонов.

Saturday, November 20th, 2010

Для тех кто ранее изучал php и привык к тому, что код как бы встраивается в страницу при переходе на Python становится актуальным вопрос : а как сделать подобное на Pyhton? Тут сделано немного не так, но тоже достаточно удобно. Дело в том, что Python изначально проектировался как полнофункциональный язык программирования, в отличии от PHP забацаного чтобы студенты могли по быстрому написать Home Page (aka хомяк). Существует несколько подходов к тому как отображать контент в веб :

  • Модель статических страниц (static page model). В первой половине 90х годов все страницы веба были статическими, то есть содержали в себе готовый документ в формате HTML. Соответственно, страницы не требовали предварительной обработки и не зависели от аргументов.
  • CGI — сценарии. Исполняемые на сервере программы используют для вывода результата библиотечные функции записи в стандартный вывод(print для языков С/C++, write для языка Pascal и т.п.). Код представления данных разбросан среди кода программы в аргументах вызовов этих функций.
  • Модель динамических страниц (dynamic page model). Не зависящая от аргументов часть страницы пишется в HTML-коде, а функциональная часть встраивается в код страницы с помощью специальных тегов — скриптлетов.
  • Модель MVC. Реализация шаблона проектирования модель-представление-контроллер (Model-View-Controller), для разделения зависимости кода представления и кода программного обеспечения, работающего с ресурсами сервера.

Последний подход все больше входит в моду и становится популярным среди web-девелоперов. Впрочем, в PHP так же есть средства (фрэймворки) позволяющие использовать эту модель по полной программе, в частности Zend Framwork.
Питон в свою очередь может похвастаться большим количеством грамотно построенных фрэймворков пользоваться которыми одно удовольсвие. Местная звезда – фрэймворк Django, на основе которого собирается сайт практически любой сложности, от форумов до блогов. И все же в чем преимущества MVC? Их несколько, одно из самых существенных – разделение кода/данных/дизайна

Ближе к делу. MVC.

Как это работает? Очень просто как следует из названия у системы 3и компонента Model, View и Controller. Каждый компонент отвечает за свою область, поэтому достаточно легко разделить усилия программистов и дизейнеров между этими частями, пусть каждый занимается своим делом.

MVC определяет способ разработки программного обеспечения при котором код для определения и доступа к данным (модель – model) отделён от логики приложения (управление – controller), которая в свою очередь отделена от интерфейса пользователя (представление – view).

Model – отвечает за представление и обработку данных. Часто используется ORM что значительно упрощает разработку.
View – отвечает за отображение информации, за представление её пользователю в удобном виде.
Controller – связывает модель и представление. Передает данные, введённые пользователем в модель другими словами является средством, при помощи которого пользователи взаимодействуют с системой.

Model View Controller

Рассмотрим View подробнее, ведь это именно то, что визуализирует сухие данные. Для представления используют так называемые Template Engines. Выглядит это примерно так :

<title>{% block title %}{% endblock %}</title>
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>

Их достаточно много, отдельно можно выделить Jinja2 и Mako. В чистом виде движки шаблонов позволяют вам генерировать статические страницы (html код). Т.е. используя движек шаблонов можно располагая какими-то данными написать код который будет собирать готовый сайт. Нужно было сгенерировать несколько сайтов используя каталог товаров, получилось примерно так :

    env = Environment(loader=FileSystemLoader(TEMPLATE_FOLDER))

    sitemap_list = []

    # render index pages
    for page, items in zip(index_pages, grouper(shop_items, ITEMS_PER_PAGE)):

        page_data = form_nav_panel(page, index_pages)
        template = env.get_template('index_pages.html')

        random_5 = random.sample(shop_items, 5)

        html = template.render(
            index_page=True,
            page_data=page_data,
            index_pages=index_pages,
            items_in_store=len(shop_items),
            current_page = page,
            items=items,
            random_5=random_5,
            current_date=datetime.now().strftime("%d. %B %Y")
        )

        with open("./sites/mystaticsite/%s" % str(page['fname']), "w") as f:
            f.write(html.encode("utf-8"))

        sm = {
            'url' : page["fname"],
            'title' : "Item list : " + str(page['id'])
        }

        sitemap_list.append(sm)

Т.е. берется шаблон (html + тэги движка шаблонов) загружается с помощью Jinja2, далее в функцию рендера передаются нужные данные, на выходе имеем готовый html код. Получать уникальные шаблоны несложно, используя плагины вроде ScrapBook. Грабим понравившуюся страницу, меняем дизайн по вкусу, расставляем тэги. Зачастую типовые страницы отличаются друг от друга в строении, но не на много (header + content + sidebar + footer). Чтобы не копировать полностью html код, переписывая тэги, Jinja2 предоставляет такую мощную фичу как наследование.

{% extends "index.html" %}

{% block title %}Fuck you spomoni{% endblock %}
{% block page_title %}(^_^){% endblock %}

{% block navigation_bar_top %}
<div id="navigation_bar">
<h1>Items in store : {{ items_in_store }}</h1>
<span>{% if page_data['prev_page_id'] is defined %}<a href="{{ page_data['prev_page_fname'] }}" rel="prev">« Previous </a>{% else %}« Previous {% endif %}</span>
{% for item in index_pages %}
{% if item['id'] == current_page['id'] %}
<span>{{ item['id'] + 1 }}</span>
{% else %}
<span><a href="{{ item['fname'] }}">{{ item['id'] + 1 }}</a></span>
{% endif %}
{% endfor %}
<span>{% if page_data['next_page_id'] is defined %}<a href="{{ page_data['next_page_fname'] }}" rel="next"> Next »</a>{% else %}Next »{% endif %}</span>
</div>
{% endblock %}

К предыдущему примеру. Это файл представляет собой шаблон “как он есть”, невооруженным глазом можно заметить что он наследуется от index.html переопределяя некоторые блоки, об этом явно говорит строчка : {% extends “index.html” %}

Вот таким образом и происходит построение сайта используя Template Engine. Если к этому добавить еще работу с БД и контроллер получится как раз таки этот самый MVC. Однако если нет необходимости часто менять контент на сайте, лучше генерировать его на стороне сервера за раз вытягивая данные из текстовых файлов или базы данных. Генерация статических сайтов, которые порадуют гугл и юзера своей скоростью загрузки, помимо этого существенно снижая скриптовую нагрузку на сервер.

Как запустить скрипт с другого IP?

Friday, November 19th, 2010

Как правило, если вы берете VDS или Dedicated сервер, в комплект идет несколько дополнительных IP адресов, обычно 2 или 4, зависит от дата центра. Вы межете без проблем развешивать сайты на разные айпи, управляя записями DNS домена. А как запустить скрипт на не основном ip адресе сервера? Один из вариантов предложил Lorien – использовать прокси сервер – Squid. О том, как установить Squid я писал ранее. Короче говоря часто на одном ипе висит куча скриптов которые дрочат какие-то сервисы время от времени, и чтобы не натыкаться на бан или превышение лимитов API лучше всего распределить нагрузку между доступными ip адресами. Это потребует небольшой модификации скриптов, нужно будет направлять запросы через прокси. “Прозрачно” это можно сделать используя библиотеку socksipy-branch.

Чтобы перенаправлять запросы на другой ип адрес используется следующая хитрая схема : мы направляем запрос на ip:port откуда squid роутит его на айпи используя директиву tcp_outgoing_address.

route script to dedicated ip

Allows you to map requests to different outgoing IP addresses based on the username or source address of the user making the request.
Позволяет вам назначать запрос на другие исходящие IP адреса, основываясь на имени или адресе источника откуда юзер сделал запрос.

Осталось только настроить конфиг Squid’а нужным образом, естественно если ипов больше чем 2а лучше всего потратить 5 минут и написать скрипт который будет генерировать нужную последовательность директив :

# Говорим squid слушать нужные порты
# http_port 20000
# http_port 20001

# Создаём ACL правила
# acl p20000 myport 20000
# acl p20001 myport 20001

# С помощью созданных ACL правил выбираем нужный исходящий IP
# tcp_outgoing_address 78.109.20.226 p20000
# tcp_outgoing_address 78.109.20.227 p20001

Взял отсюда. Немного переделал приблизив скрипт к “боевым” условиям. Список айпи берет из файла ips.txt. Начальный порт задаем в start_port.

Внимание, лучше лишний раз проверить, чтобы на ипах ничего не висело. Делается это с помощью команды : netstat -tulnap

start_port = 2000
ips_list = [ item.strip() for item in open("ips.txt", "r").readlines()]

chunks = ([], [], [])

for num, ip in enumerate(ips_list):
    port = start_port + num
    chunks[0].append('http_port %d' % port)
    chunks[1].append('acl p%d  myport %d' % (port, port))
    chunks[2].append('tcp_outgoing_address %s p%d' % (ip, port))

for group in chunks:
    for line in group:
        print line
    print

print "-------------------------------\n"

Если кто знает более простой способ welcome в комменты. Я задавал это вопрос на freenode #linux (IRC канал), но практичного решения с ходу никто не предложил. Пока что единственный рабочий вариант предложил Lorien.

Регулярные выражения в Python

Thursday, November 18th, 2010

Регулярные выражения (они же регулярки, они же регэкспы) совершили настоящую революцию в обработке текстов, позволяя вести поиск и вставку текста используя так называемые паттерны – описывающие требуемый формат операции. Само по себе описание регекспов достаточно объемно, для повседневных задач можно даже изучить тему вполне поверхностно. Использовать регулярки, крайне удобно и быстро, несмотря на то что по скорости они проигрывают строковым и DOM функциям – тем не менее часто проще написать регулярку чем разрабатывать функцию. Само собой каждый уважающий себя язык программирования имеет реализацию регэкспов и Python не исключение. В качества классического примера :

def parse_proxy(page):
    """Parse proxies from webpage"""
    reg = re.compile("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}")
    proxy_list = reg.findall(page)
    return proxy_list

вытащить все прокси из кода вебстраницы. Простейшие регулярки несколько раз используются в прокси чекере.

Полезные сайты :
http://www.pcre.ru/ – типичные примеры, описание и конструктор который сильно облегчает процесс конструирования регулярных выражений.
http://www.regexlib.com/ – библиотека готовых регулярных выражений, сортировака по разделам. Очень полезный ресурс.
http://www.gskinner.com/RegExr/ – еще один конструктор регулярных выражений. Составь и проверь.
http://regexlib.ru/ – еще одна библиотека регулярок. на русском.

регулярные выражения

Использование регулярных выражений на Python.

Питон естественно предоставляет инструменты для работы с регулярными выражениям

http://docs.python.org/library/re.html
http://docs.python.org/dev/howto/regex.html – есть неплохой HOWTO

Библиотека регулярных выражений называется – re. Немаловажный момент – для строк с регулярным выражением нужно использовать префикс “r“, чтобы символы \ не преобразовывались в строковые специальные символы вроде \t, \n и т.д.

Использовать так :

match = re.search(ur"text", u"sometext and text")
print  "Re.seach : ", match.group()
exp = re.compile(ur"text")
match = re.finditer(exp, u"sometext and text")
print "Re.finditer : "
for item in match:
    print item.group(), item.span()

re.compile – компилирует регулярное выражение в regular expression object который может быть использован методами match() и search() и т.д. К выражению могут быть добавлены специальные флаги-модификаторы (вроде re.IGNORECASE).

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

group() возвращеает строку удовлетворяющую условию регэкспа.
start() Возвращает начальную позицию совпадения
end() Возвращает конечную позицию совпадения
span() Возвращает кортеж (tuple) – (start, end) в котором заданы позиции совпадения.

Следующий пример возвращает все числа из произвольной строки :

p = re.compile('\d+')
result = p.findall('1 2 3 yolochka gori, 23 yellow popugais')
print result

Целесообразность применения регулярных выражений.

Однако не стоит чересчур увлекаться регулярными выражениями (об этом говорят даже в официальном туториале python’а), зачастую бывает проще воспользоваться строковыми функциями – они быстрее (т.к. реализованы в виде небольших, хорошо оптимизированных C циклов). В моей практике бывали случаи когда самый простой путь был – через DOM вырезать нужный кусок и уже там работать регулярками (парсинг google images, например). Представим что вам нужно заменить слово “милиция” на “полиция”, для этого вполне подойдет функция re.sub, однако в РАЗЫ проще использовать replace() :

text = "Наша милиция нас бережет."
result = text.replace("милиция", "полиция")
print result

Разница между match() и search()

Функция match() только проверяет – есть ли совпадения с начала строки, в то время как search() будет сканировать на совпадения с паттерном всю строку целиком.

print(re.match('super', 'superstition').span())
print(re.match('super', 'insuperable'))
print
print(re.search('super', 'superstition').span())
print(re.search('super', 'insuperable').span())

(0, 5)
None

(0, 5)
(2, 7)

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

Функции map и zip и lambda. Python

Wednesday, November 17th, 2010

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

Функции map, zip и lambda в примерах.

Простая задача есть список a = [1, 2] и список b = [3, 4] одинаковой длины и нужно слить их парами. Проще простого – используя функцию zip :

a = [1,2]
b = [3,4]
print zip(a,b)
[(1, 3), (2, 4)]

или тройками :

a = [1,2]
b = [3,4]
c = [5,6]
print zip(a,b,c)
[(1, 3, 5), (2, 4, 6)]

или в более общем виде

list = [a, b, c]
print zip(*list)
[(1, 3, 5), (2, 4, 6)]

Звездочка * перед list как-бы говорит что передается список аргументов, т.е. Действовать эквивалентно тому как если бы передали a, b, c т.е. Можно даже так print zip(*[a, b, c]) результат не изменится.

Далее функция – map. Случаются ситуации, когда внезапно нужно применить какую-либо функцию к каждому элементу списка.
Нуб напишет так :

def f(x):
    return x*x
nums = [1, 2, 3]
results = []
for num in nums:
    results.append(f(num))
print results

Немного поизучавший мануалы так :

def f(x):
    return x*x
print [ f(num) for num in nums ]

Программист сделает проще :

def f(x):
    return x*x
print map(f, nums)

А вот тру-мэдскиллз кодер сделает следующим образом :

print map(lambda x: x*x, nums)

Последняя запись являет собой пример наиболее грамотного подхода. Дело в том, что когда человек пишет код как стихи в порыве вдохновения, крайне роляет скорость написания (отсюда растут корни трепетной любви многих питон кодеров к vim и emacs), а сильная сторона питона как раз в размере генерируемого кода – он очень компактный. Написать одну строчку естественно быстрее чем 7, да и изучать короткий код проще, однако написание подобного кода требует определенного навыка. Другая сторона медали – иногда про-devs очень любят писать в одну строчку целые последовательности достаточно сложных действий, да так что очень трудно понять что там происходит и что получается в конечном итоге.

Из примера понятно, что map применяет какую-либо функцию к списку и возвращает результат опять же в виде списка. Вы можете передать несколько списков, тогда функция (идущая первым параметром) должна принимать несколько аргументов (по количеству списков переданных в map) .

def f(x, y):
    return x*y

a = [1,3,4]
b = [3,4,5]
print map(f, a, b)
[3, 12, 20]

Жир, правда?

Однако если списки разной длины, т.е. Один короче другого, то он будет дополнен значениями None до нужной длины. Если убрать из списка b последнее значение – пример не будет работать, т.к. В функции f произойдет попытка умножения числа на None, а в питоне строгая типизация, что кстати выгодно отличает его от php, который в подобной ситуации работал бы дальше.
Поэтому если функция f достаточно объемна, неплохо бы проверять передаваемые значения. Например ;

def f(x, y):
    if (y == None):
        y = 1
    return x*y

Если же заместо функции стоит None – то map действует примерно так же как и zip, но если передаваемые списки разной длины в результат будет писаться None – что кстати очень уместно в некоторых моментах.

a = [1,3,4]
b = [3,4]
print map(None, a, b)
[(1, 3), (3, 4), (4, None)]

Теперь про лямбда функции в python. Они используются когда вам необходимо определить функцию, ведь часто (как в предыдущих примерах) функция настолько мала, что определять её отдельно смыла нет (ведь это лишние строчки кода и ухудшение читабельности).
Поэтому функцию можно определить “на месте” f = lambda x: x*x как бы говорит нам – принимает x, возвращает x*x

Так используя стандартные инструменты питона можно записать довольно сложные действия в одну строчку. К примеру функцию :

def f(x, y):
    if (y == None):
        y = 1
    return x*y

можно представить как :

lambda x, y: x * (y if y is not None else 1)

А теперь хорошо бы передавать списки отсортированные по длине – len(a) > (b) – проще простого – воспользуемся функцией sorted :

sorted([a, b], key=lambda x: len(x), reverse=True)

фунция sorted принимает список значений ([a,b] = [[1,2],[2,4,5]]) и сортирует по ключу key – который у нас задан функцией len(x) – возвращающей длину списка, сортируем в порядке убывания (reverse=True)

В конечном итоге вся операция записывается таким образом :

map(lambda x, y: x * (y if y is not None else 1), *sorted([a, b], key=lambda x: len(x), reverse=True))

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

Как мониторить mySQL запросы к базе данных?

Sunday, November 14th, 2010

Зачем? Предположим у вас есть CMS и хочется устроить там искусственную жизнь, естественно самый простой вариант (и самый быстрый) – работать напрямую с базой данных. Но если cms достаточно развитая то возникают сложности, из-за того что одно действие меняет данные в куче разных таблиц. Естественно очень хотелось бы мониторить обращения к базе данных, чтобы потом их повторить. Ну, во-первых нужен линукс – web-разработчик должен работать в линуксе. У меня стоит нечестная Ubuntu – нечестная потому что в окне VirtualBox, впрочем, про это я расскажу позже.

Перехват обращений к базе данных mySQL

Для того чтобы просматривать запросы нужно включить логгирование в конфигурационном файле mysql он находится /etc/mysql/my.cnf нужно раскоментировать следующие 2е строчки :

#
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
# Be aware that this log type is a performance killer.

log = /var/log/mysql/mysql.log
general_log             = 1

Далее сделать рестарт mySQL сервера :
sudo /etc/init.d/mysql restart
Все, лог будет писаться в /var/log/mysql/mysql.log Рестарт mySQL сервера только не забудьте сделать.

перехват запросов к MySQL

Можно наблюдать в это в реальном времени в окне терминала :
tail -f /var/log/mysql/mysql.log

Прокси чекер на Python.

Sunday, November 14th, 2010

Как написать многопоточный прокси чекер на Python? Как нефиг делать =) Я уже писал немного о том как проверять прокси на alive, с тех пор прошло много времени и чекер немного усовершенствовался. Изначально я передал материал на форум Privatetalks, но теперь пришло время пополнить им блог. Исходные ходы поставляются как есть, в отрыве от контекста, собственно для тех кто шарит не составит труда доработать и реализовать многопоточность (на ActiveState и StackOverflow есть уже готовые решения по этой части).

Многопоточный чекер проксейВсе просто. Есть какая-то страница, которую нужно запрашивать через прокси, и проверят что там отдали. Помимо этой простейшей проверки на метод GET, есть еще проверки на POST и Cookie, некоторые прокси не держат, и поэтому часто бывают бесполезны для каких-то задач. Проверка на куки мне пока была не нужна, а вот проверку на POST я сделал.

TProxy – класс который обеспечивает работу с данными прокси. Такая тема в программировании называется – инкапсуляция.

На сервере нужно разместить несколько файлов с которыми будет взаимодействовать скрипт. Можно размещать и скрипт и эти файлы на одном сервере, я так и делал =) правда тогда будьте осторожны с многопоточностью у меня скрпит в 300 потоков бодро ложил апачи (не всегда, но бывало), на неслабом железе.
Предположим это index.php :

<html>
<head>
</head>
<body><h1>SIGNATURE</h1>
<h2>Real IP : xx.xx.xx.xx</h2>
<h2>IP : xx.xx.xx.xx</h2>
</body>
</html>

SIGNATURE – уникальный идентификатор страницы. должен совпадать с CHECK_STR. Еще нужно определить 2е “константы” CHECK_URL – урл где лежит вышеприведенная страница, и CHECK_MAX_TIMEOUT – максимальный таймаут (если отклик через прокси больше, то она помечается как bad) поставьте 2.0 для начала.
Как формируются Real IP и IP? Getting real IP address in PHP – вообщем с помощью этого кода нужно сформировать Real IP и IP.
А вот тут умные дядьки пишут как чекать геолокейшн – Check GEO Location. В принципе, я так понимаю таких сервисов много и можно долбить следующий если первый не вернул адекватный результат.

def check_proxy(proxy, need_country=False):
    """Check if proxy alive + anonymity and record proxy to file if we need this"""
    ip = TProxy(proxy)

    gt = urllib2.build_opener(urllib2.ProxyHandler({"http":ip.get_proxy()}))
    start_time = time.time()
    try:
        result = gt.open(CHECK_URL, timeout=CHECK_MAX_TIMEOUT)
        result = result.read()
    except (urllib2.URLError, socket.timeout, httplib.BadStatusLine, httplib.InvalidURL):
        ip.set_alive_status(False)
        return ip
    except:
        ip.set_alive_status(False)
        return ip

    ip.set_alive_status(True)
    ip.set_timout(time.time() - start_time)     # proxy response time

    # get ip and real ip values. check for anonymity
    search = re.compile(CHECK_STR)
    pattern = re.search(search, result)

    if pattern != None:
        ip.set_alive_status(True)
        search = re.compile("IP : \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}")
        ips = re.findall(search, result)
        # extract ip and real ip values from page
        if ips != []:
            try:
                real_ip = ips[0]
                given_ip = ips[1]
                if real_ip == given_ip:
                    ip.set_anonymous_status(True)
            except:
                ip.set_alive_status(False)
                return ip

        # check country
        if need_country:
            try:
                response = gt.open('http://api.hostip.info/get_html.php?ip=%s' % ip.get_host(), timeout=5).read()
                country = re.search('Country: (.*)', response)
                if country <> "":
                    ip.set_country(country.group(1))
                else:
                    ip.set_country('undefined')
            except:
                ip.set_country('undefined')
    return ip

Теперь как проверить на POST.

def generate_random_str(length=10):
    str = string.lowercase+string.digits
    return ''.join(random.sample(str, length))

def check_proxy_for_post(proxy):
    token = generate_random_str(20)
    try:
        gt = urllib2.build_opener(urllib2.ProxyHandler({"http":proxy}))
        post_data = urllib.urlencode({'zpost' : token})
        response = gt.open(CHECK_URL + "post.php", post_data, timeout=POST_MAX_TIMEOUT).read()
        # check token
        print response
        search = re.compile(token)
        pattern = re.search(search, response)
        if pattern != None:
            return True
        else:
            return False
    except HTTPError, e:
        print "Http error"
        return False
    except URLError, e:
        print "Url error"
        return False
    except:
        print "Unknown error"
        return False

Легко встраивается в функцию check_proxy приведенную выше. Нужно только немножко пошевелить мозгами.
в файл index.php добавляется форма :

<form action="post.php" "method="post">
<input type="text" name="zpost" value="post check">
<input type="submit" value="Check POST method">
</form>

В ту же папочку аккуратно ложится файлик

<html>
<body>
<h1><?php echo $_POST["zpost"]; ?></h1>
</body>
</html>

Вообщем код легко собирается в готовый продукт, добавляются фичи по вашему вкусу и вперед ура.
Кстати говоря готовый код недавно обнаружил на гитхабе – чекер прокси. Оттуда тоже можно взять несколько идей.

А еще нужно не жадничать и быть аккуратным т.к. ДЦ может абузить по подозрению в Netscan.

Понравилась статья? Зарегайся на форуме privatetalks – общайся с профессионалами.

Самый быстрый способ удалить дубли из списка. Python

Sunday, November 14th, 2010

Задача классическая. Удалить повторы из какого-либо списка. Самый быстрый вариант сделать так :

def uniq(seq):
    """The fastest way to unique list"""
    seen = set()
    seen_add = seen.add
    return [ x for x in seq if x not in seen and not seen_add(x)]

Хотите 10 000 друзей на фэйсбуке?

Sunday, November 14th, 2010

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

мой фэйсбук

мой твиттерДесят тысяч причин по которым вы хотите иметь 10к друзей.

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

  1. Вы станете популярным. Школиё говорит что имеет 500 или 1000 друзей? Вы сможете сказать – “У меня 10k”
  2. Вы станете получать friend requests каждый день сотнями, и все потому, что ваш никнейм есть на многих страницах фэйсбука.
  3. У вас есть страница которую вы хотите промоутить? Хотите чтобы пара тысяч ваших друзей пошли и посмотрели на нее?
  4. У вас есть продукт или услуга которую вы хотите промоутить, но вам нужны люде чтобы генерировать продажи?
  5. Покупать рекламу – дорого
  6. Возможно в будущем вы сможете продать профиль ради easy money? Это уже такая же обыденность как и продажа раскрученных блогов.
  7. Можно продавать ссылки и рекламу с вашего профиля. Бизнесмены и веб-сайты будут платить вам за то, чтобы вы поставили ссылку на их сайт.
  8. Вы актер/музыкант и хотите рекламировать ваши пати?
  9. Вам нравится смотреть как ваш трафик растет.
  10. Вы просто хотите иметь 10к друзей.

Самый быстрый способ взять планку 10к очевидно как можно большая активность в социальной сети. Вам нужно наращивать присутствие – добавлять друзей, делать комментарии, постить анонсы и сообщения. Делать быстро и много. Быть всегда и во многих местах сразу.

Добавляйте друзей как только есть такая возможность.

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

ВСЕГДА добавляйте рекомендованных друзей.

Это отличный инструмент от фэйсбука, почему бы не использовать его?

Используйте кнопки.

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

Вступайте в группы.

Вступление в тематические группы позволит вам построить сеть тематических знакомств. Нельзя не использовать эту возможность.

Делайте ваши собственные группы.

Создавайте взаимодействия сами – делайте группы, приглашайте знакомых. Приглашайте своих RL друзей. Возможно не все ваши друзья/коллеги еще имеют аккунт в социальной сети? Отличный повод приглисить их!

Постите комменты в популярных профилях.

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

Используйте ссылку – Add me

Используйте shor url сервис вроде – bit.ly для сокращения ссылки и теперь добляйте её в конец каждого емэйла которое вы отправляете, если у вас есть профиль на посещаемом форуме – поставьте ссылку в сигнатуру.

Как подобрать палитру для сайта?

Sunday, November 14th, 2010

Так же как в музыке есть определенные правила при построении аккордов так же и цветовая палитра строится по определенным правилам, зачастую бывает тяжело с ходу подбирать нужные цвета и их правильные сочетания. Во первых это время, а во вторых хотелось бы в таких вопросах полагаться на специалистов. Обе проблемы легко решаются если использовать социальную сеть Color Lovers.

социальная сеть для дизайнеров

Внутри мы видем классическую twitter-like социальную сеть. Пользователи могут предлагать свои решения в области цветового дизайна и так же голосовать за понравившиеся. Есть возможность фалловить. Порыскав там немного нашел массу готовых решений и цветовых схем. Если вы больше программист, чем дизайнер или по каким-то причинам не хотите заниматься подбором цветов – эта социальная сеть – то что нужно.

Блог теперь do-follow

Sunday, November 14th, 2010

Поставил do-follow на комментарии, теперь любой кто напишет комментарий получит бэклинк на свой сайт/блог. + Посидел вечер за правкой кода и css, внес массу незначительных изменений, чтобы блог выглядел более web 2.0′ым. В ближайшее время (благо оно появилось, хотя, как не странно работать стал больше, главное втянуться) продолжу допиливать дизайн : хочу практически полностью отказаться от картинок и сделать все на css. Не помешало бы еще и как ускорить загрузку блога, гугл любит когда сайт быстрый =) да и пользователям это по нраву.

My blog is Do-Follow


Пишу код, делаю сайты.
Check out my about.me profile!

парсинг сайтов, форумов, интернет магазинов

Want to subscribe?

istinspring twitter account
istinspring facebook account

 Subscribe in a reader Or, subscribe via email:
Enter your email address:  
Find entries :