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

Archive for August, 2009

Распараллеливание задач. Python. Web. #1

Wednesday, August 19th, 2009

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

Тема поста, как можно догадаться из названия потоки. Если однопоточное приложение – это конвеер, то многопоточное – целый завод, позволяющий выпускать больше “фирменной продукции” за меньшее время (более эффективно использовать вычислительные ресурсы). Другими словами потоки безусловно полезная тема, которая стоит того, чтобы потратить некоторое время на изучение, чтобы так сказать познать ДАО. Тема объемная, сам я тоже не профессиональный программист, нет никакой возможности описать все одним постом => разобью задачу на подзадачи.

Python – Global Interpreter Lock (GIL)

Python обладает некоторым преимуществом в реализации потоков по сравнению с php (по крайней мере так принято считать), но как обычно не все так гладко =) Python – интерпретатор, и если верить девелоперам существует проблема которая называется GIL – global interpreter lock.

При своей работе основной интерпретатор Python постоянно использует большое количество потоково-небезопасных данных. В основном это словари, в которых хранятся атрибуты объектов. Для избежания разрушения этих данных при совместной модификации из разных потоков перед началом исполнения нескольких инструкций (по умолчанию 100) поток интерпретатора захватывает GIL, а по окончании освобождает. Вследствие этой особенности в каждый момент времени может исполняться только один поток Python кода, даже если в компьютере имеется несколько процессоров или процессорных ядер.

Взял из википедии

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

Если интересуют детали – более подробно и наглядно про GIL можно почитать в этом дукументе или посмотреть видео.

Ближе к делу – пора сделать что-нибудь полезное.

Пингуем сайты

Предположим, что вы счастливый вледелец целой сетки блогов/сайтов разбросанных для надежности и перелинковки по разным хостингам. Хорошо было бы переодически проверять сайты на работоспособность, ок – можно проверить вбивая адреса в браузер. Это замечательно если сайтов меньше 10, а если 100? или 1000? Проверка большого количества может стать действительно проблемой которая сожрет кучу времени (хехе я бы на самом деле положил болт на это занятие и уверен 90% вебмастеров поступили бы точно так же). Но тут грамотного вебмастера может выручить несложная автоматизация.

Собственно можно пойти 2я путями – тупо вызывать утилиту ping и парсить результаты, или использовать сокеты для того чтобы формировать/отправлять/получать пакеты используя стандартный потокол ICMP. 1ый способ годится если гонять программку на строго заданной ос, 2ой более универсален.

Собственно реализация 1го способа для Linux который я выдрал где-то в интернете :

import os
import re
import time
import sys
from threading import Thread

class testit(Thread):
    def __init__ (self,ip):
        Thread.__init__(self)
        self.ip = ip
        self.status = -1
    def run(self):
        pingaling = os.popen("ping -q -c2 "+self.ip,"r")
        while 1:
            line = pingaling.readline()
            if not line: break
            igot = re.findall(testit.lifeline,line)
            if igot:
                self.status = int(igot[0])

testit.lifeline = re.compile(r"(\d) received")
report = ("No response","Partial Response","Alive")

print time.ctime()

pinglist = []

for host in range(60,70):
    ip = "192.168.200."+str(host)
    current = testit(ip)
    pinglist.append(current)
    current.start()

for pingle in pinglist:
    pingle.join()
    print "Status from ",pingle.ip,"is",report[pingle.status]

print time.ctime()

2ой способ который я слепил из сниппетов можно скачать тут.

Нетрудно заметить – кода больше, но много лишнего, пример написан на скорую руку но тем не менее все должно быть понятно. Есть только одно “но”, если список хостов довольно объемный программа породит огромное количество потоков (по одному на каждый), что не совсем верно, это распиздяйский подход. Чтобы этого избежать реализуется так называемый пул потоков (thread pool) – т.е. создание ограниченного числа потоков которые обрабатывают задания из очереди. Это тема следующей статьи.

Постинг в wordpress.

Tuesday, August 18th, 2009

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

import wordpresslib
url = 'http://www.mysite.com/wordpress/xmlrpc.php'
wp = wordpresslib.WordPressClient(url, 'username', 'password')
wp.selectBlog(0)
post = wordpresslib.WordPressPost()
post.title = 'Post title'
post.description = 'Post content'
idPost = wp.newPost(post, True)

Заявленные функции :

  • Создание новых постов
  • Редактирование старых
  • Публикация “черновиков” (т.е. ранее сохраненных но неопубликованных)
  • Удаление постов
  • Изменение категорий привязанных к посту
  • Информация по  блогу и пользователям
  • Загрузка мультимедиа файлов (фотографии & видео)
  • Получить последний пост/пинги/трекбэки

Проверка прокси – простейший Proxy Checker.

Friday, August 14th, 2009

Недавно возникла задача проверять прокси из списка. Посмотрев в гугл, нашел следующий код :

import urllib2
import socket

def is_bad_proxy(pip):
    try:
        proxy_handler = urllib2.ProxyHandler({'http': pip})
        opener = urllib2.build_opener(proxy_handler)
        opener.addheaders = [('User-agent', 'Mozilla/5.0')]
        urllib2.install_opener(opener)
        req=urllib2.Request('http://www.example.com')  # change the URL to test here
        sock=urllib2.urlopen(req)
    except urllib2.HTTPError, e:
        print 'Error code: ', e.code
        return e.code
    except Exception, detail:
        print "ERROR:", detail
        return True
    return False

def main():
    socket.setdefaulttimeout(120)

    # two sample proxy IPs
    proxyList = ['125.76.226.9:80', '213.55.87.162:6588']

    for currentProxy in proxyList:
        if is_bad_proxy(currentProxy):
            print "Bad Proxy %s" % (currentProxy)
        else:
            print "%s is working" % (currentProxy)

if __name__ == '__main__':
    main()

Все просто, пытаемся открыть ресурс по адресу example.com (который 100% работает), если открыли – все ок, если нет – то нет. Подгрузить список проксей можно и из файла например так :

# Just load list from file
def LoadListFromFile(filename):
    result = []
    fileIn = open(filename, 'r')
    for line in fileIn:
        result.append(line.strip())
    fileIn.close()
    return result

Анализ Google SERP на Python

Tuesday, August 11th, 2009

Хотел написать для начала, что нибудь вроде  “Выдача гугла – бесценный источник информации”, ну да ладно, все мы знаем зачем вебмастеру понадобилось вдруг анализировать топы гугла по спискам кейвордов или хуже того парсить урлы/отслеживать позиции сайтов =) вообщем предельно ясно, что задача анализа результатов выдачи возникает часто и найти применение результатам не проблема. Сложность только в том, что нужно писать код, причем желательно быстро и с минимальными усилиями. Помимо самих SERP было бы неплохо узнать и ключевые параметры – PR (PageRank) и Index, полезная информация, я гарантирую. Некоторое время назад, я кодил на PHP, потом бросил, бесит отсутствие строгой типизации (и потоков, да и тем кто с детства привык к красоте и логичности кода на Object Pascal/C++ пхп должен быть глубоко противен), еще и что-нибудь вроде WAMP/XAMPP поднимать на локальном компе. Python ничуть не хуже все к чему привыкли на PHP есть и на Python.

Для желающих приобщиться доступен Complete and Ready-to-Install industry standard Python distribution – после установки можно сразу приступать к работе, именно в таком виде должен поставляться язык программирования.

Итак для начала нужно получить данные от гугла, можно попробовать делать это через curl/liburl, но это hard-style, если погуглить можно легко найти уже готовые решения. Я уже озаботился в свое время поиском библиотеки, поэтому сразу даю линк на пост автора – Python Library for Google Search, с примерами и описанием. Библиотека избавляет вас от деталей предоставляя интерфейс позволяющий легко и изящьно работать с выдачей. Просто закиньте содержимое архива в Python\Lib или в папку где находиться ваша программа.

Код шлет запрос к гуглу и выводит в окно Python Shell результаты, обратите внимание на конструкцию try/except – позволит избежать остановки программы в случае ошибки :

from xgoogle.search import GoogleSearch, SearchError
try:
  gs = GoogleSearch("hot black chicks", random_agent=True)
  gs.results_per_page = 10
  results = gs.get_results()
  for res in results:
    print res.title.encode('utf8')
    print res.desc.encode('utf8')
    print res.url.encode('utf8')
    print
except SearchError, e:
  print "Search failed: %s" % e

Количество страниц в индексе гугла для домена определим сформировав запрос вида “site:site_url” и поглядев на кол-во результатов :

def GetGoogleIndex(self, url):
    request = 'site:' + url
    index = 0
    try:
        gs = GoogleSearch(request)
        gs.results_per_page = 10
        results = gs.get_results()
        index = gs.num_results
    except SearchError, e:
        index = -1
        print "Search Failed : %s" % e
    finally:
        print "Index: %d\tURL: %s" % (int(index), url)
        return index

С определением PR все непросто, но это не важно, т.к. в интернете несложно найти уже готовый код :
Google PR checker Python code

Результаты можно писать в файлы/базу данных SQL/SQLite, но лучше естественно в базу, проще будет делать выборки. Готовый и отлаженный код без проблем переносится на сервер, при желании реализуется многопоточность, но в этом случае скорее всего придеться дрочить гугл через прокси (код библиотеки открыт, как включить прокси смотреть тут и тут)

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 :