Памятка примерная, без команд, названия пакетов неточные.
1) Скачал курл с оф. сайта, скомпилил, установил.
2) Удалил libcurl3-gnutls и libcurl3.
3) Установил пакеты python-dev и libcurl-openssl-dev.
4) pip install pycurl. Получил pycurl с последней версией libcurl, а также с openssl вместо gnutls. Не знаю, что лучше, просто openssl было привычнее, плюс какая-то ошибка была у gnutls.
вторник, 13 ноября 2012 г.
пятница, 1 июня 2012 г.
grab.spider tricks.
1) Дефолтный valid_status для всех заданий. Нужно переопределить метод valid_response_code, например таким образом:
В данном примере все ответы будут считаться валидными.
2) Список стартовых урл, initial_urls, может оказаться просто ненужным. Чтобы не делать лишнее действие, можно запускать spider не через task_initial, а через task_generator:
Это один из способов, но далеко не единственный.
def valid_response_code(self, code, task):
return True
В данном примере все ответы будут считаться валидными.
2) Список стартовых урл, initial_urls, может оказаться просто ненужным. Чтобы не делать лишнее действие, можно запускать spider не через task_initial, а через task_generator:
class MainSpider(Spider):
#initial_urls = ['http://www.google.com/']
def task_generator(self):
url = "http://www.google.com/"
yield Task(name='page', url=url)
Это один из способов, но далеко не единственный.
вторник, 29 мая 2012 г.
Собираем pycurl под windows (python 2.7).
Наверняка сейчас под windows pycurl у всех стоит вот с этого сайта , к сожалению, в этой версии есть такой неприятный баг, который неизвестно при каких условиях проявляется. Таким образом, необходимо собрать версию поновее, ибо больше сайтов со сборками pycurl я не видел.
Всё делал вот по этой статье http://curl.haxx.se/mail/curlpython-2009-11/0010.html за исключением небольшого ньюанса с ассемблером.
Для работы необходимо установить:
1) Visual Studio C++ Express (я ставил 2008).
2) Perl (я качал вот этот http://www.activestate.com/activeperl/downloads)
3) Ассемблер Nasm, а также добавить путь до bin в переменную path (брать отсюда http://www.nasm.us/)
Чтобы собрать pycurl нам надо собрать по статической библиотеке(.lib) из исходников для каждого из 3х составляющих, в скобках указаны версии которые я использовал:
zlib - http://www.zlib.net/ (1.2.7)
openssl - http://www.openssl.org/source/ (1.0.1с)
curl - http://curl.haxx.se/download.html (7.26.0)
И, конечно же, нам понадобятся исходники самого pycurl:
pycurl - http://pycurl.sourceforge.net/download/ (7.19.0)
Итак, создаем на диске С: в корне папку build и помещаем в неё все 4 папки:
Открываем Visual C++ Command Line, переходим в папку с zlib и прописываем: nmake -f win32\MakeFile.msc
Без проблем собирается и в корне появляется файл zlib.lib
На очереди openssl, переходим в его папку и прописываем команды:
1) perl Configure VC-WIN32
2) ms\do_nasm.bat
3) nmake -f ms\nt.mak
После компиляции в out32 должны появится два файла *.lib
Переходим в папку c curl и пишем: nmake vc-ssl-zlib WINDOWS_SSPI=1 VC=vc9 OPENSSL_PATH=С:\build\openssl-1.0.1c ZLIB_PATH=C:\build\zlib-1.2.7
Наконец, собираем pycurl. Для этого качаем скрипт, распаковываем содержимое архива в папку с pycurl, переходим с помощью командной строки в неё и пишем: python setup_win32_ssl_own.py --curl-dir=..\curl-7.26.0 --openssl-dir=..\openssl-1.0.1с --zlib-dir=..\zlib-1.2.7 bdist_msi
В папке dist должен появится файл pycurl-ssl-7.19.0.win32-py2.7.msi
Всё делал вот по этой статье http://curl.haxx.se/mail/curlpython-2009-11/0010.html за исключением небольшого ньюанса с ассемблером.
Для работы необходимо установить:
1) Visual Studio C++ Express (я ставил 2008).
2) Perl (я качал вот этот http://www.activestate.com/activeperl/downloads)
3) Ассемблер Nasm, а также добавить путь до bin в переменную path (брать отсюда http://www.nasm.us/)
Чтобы собрать pycurl нам надо собрать по статической библиотеке(.lib) из исходников для каждого из 3х составляющих, в скобках указаны версии которые я использовал:
zlib - http://www.zlib.net/ (1.2.7)
openssl - http://www.openssl.org/source/ (1.0.1с)
curl - http://curl.haxx.se/download.html (7.26.0)
И, конечно же, нам понадобятся исходники самого pycurl:
pycurl - http://pycurl.sourceforge.net/download/ (7.19.0)
Итак, создаем на диске С: в корне папку build и помещаем в неё все 4 папки:
- curl-7.26.0
- openssl-1.0.1с
- pycurl-7.19.0
- zlib-1.2.7
Открываем Visual C++ Command Line, переходим в папку с zlib и прописываем: nmake -f win32\MakeFile.msc
Без проблем собирается и в корне появляется файл zlib.lib
На очереди openssl, переходим в его папку и прописываем команды:
1) perl Configure VC-WIN32
2) ms\do_nasm.bat
3) nmake -f ms\nt.mak
После компиляции в out32 должны появится два файла *.lib
Переходим в папку c curl и пишем: nmake vc-ssl-zlib WINDOWS_SSPI=1 VC=vc9 OPENSSL_PATH=С:\build\openssl-1.0.1c ZLIB_PATH=C:\build\zlib-1.2.7
Наконец, собираем pycurl. Для этого качаем скрипт, распаковываем содержимое архива в папку с pycurl, переходим с помощью командной строки в неё и пишем: python setup_win32_ssl_own.py --curl-dir=..\curl-7.26.0 --openssl-dir=..\openssl-1.0.1с --zlib-dir=..\zlib-1.2.7 bdist_msi
В папке dist должен появится файл pycurl-ssl-7.19.0.win32-py2.7.msi
четверг, 23 февраля 2012 г.
Парсер Grab:Spider.
Вот ссылка о нём. Парсер на пару строк, парсит 10к популярных фильмов с кинопоиска:
Процесс парсинга занимает 3-5 секунд!
from grab.spider import Spider, Task, Data
from grab.tools.logs import default_logging
from grab import Grab
import re
class KinoSpider(Spider):
def task_initial(self, grab, task):
for xpath in grab.tree.xpath('//*/div[@class="stat"]/div/a'):
name = xpath.text_content().encode('utf8')
name = re.sub("\(.*?\)",'',name)
self.out.write(name+"\n")
self.out.flush()
def main():
initial_urls = ["http://www.kinopoisk.ru/level/56/day/2012-02-22/page/{0}/".format(x) for x in xrange(1,51)]
threads = 50
default_logging(grab_log="log/log.txt")
fl = open("out.txt","w")
bot = KinoSpider(thread_number=threads,network_try_limit=2)
bot.initial_urls = initial_urls
bot.out = fl
try: bot.run()
except KeyboardInterrupt: pass
fl.close()
print bot.render_stats()
if __name__ == '__main__':
main()
Процесс парсинга занимает 3-5 секунд!
суббота, 11 февраля 2012 г.
Свой дистрибутив Python для Windows.
Создал свой дистрибутив python с блекджеком и шлюхами (grab, lxml, pycurl, mysql, sqlalchemy, setuptools). Сделал это с помощью программы installshield, просто закинул необходимые модули в site-packages. Давно это надо было сделать, а то запарило уже всем подряд объяснять, скачай тут, запусти то, пропиши setup.py install...
понедельник, 30 января 2012 г.
sqlalchemy
Sqlalchemy - фреймворк для работы с базами данных с технолгией ORM. Почитать про него можно тут. Моей задачей было понять, как использовать этот фреймворк в потоках.
Один интересный момент, account, созданный в одном потоке и переданный в другой, изменить не получится.
Если мы поменяем атрибуты account в новом потоке и выполним Session.commit() - таблица не обновится.
import sqlalchemy
from sqlalchemy.orm import sessionmaker, scoped_session
connection = "mysql://root:@localhost/mydatabase"
# pool_size - указывает сколько запросов хранить в очереди, если будет больше, вылетит exception
engine = sqlalchemy.create_engine(connection, pool_size=30)
# Создаем объект Session и дальше во всех потоках используем только его.
Session = scoped_session(sessionmaker(bind=engine))
#Accounts - моя таблица, к которой мне нужно делать запросы, код по настройке отображения я опустил.
accounts = Session.query(Accounts)
account = accounts[0]
Один интересный момент, account, созданный в одном потоке и переданный в другой, изменить не получится.
Если мы поменяем атрибуты account в новом потоке и выполним Session.commit() - таблица не обновится.
суббота, 14 января 2012 г.
Threading и KeyboardInterrupt.
Как организовать пул потоков? Допустим у меня есть 100 данных (пусть они находятся в каком-либо списке) и все их нужно переработать в 10 потоков. Стартуем 10 потоков, в каждый передаем по 1 данному, следим за потоками, как только один отработал, стартуем новый и так пока не закончатся данные... В общем, это не то, чтобы бред, но есть способ поудобней.
За всё время работы скрипта, стартует только 10 потоков, просто каждый из них, отработав со своим 1 данным, не дохнет, а берет из списка следующее 1 данное и делает с ним эту же работу:
И, в общем, хотелось бы еще, чтобы можно всё это в любой момент можно было бы остановить. Но поскольку мы выполнение программы блокируем с помощью queue.join(), то скрипт наши Ctr+C банально "не услышит". Я начал искать, что делать в таком случае, нашел вот такое решение, но у меня оно работало абы как. А потом, поразмыслив, я сам придумал решение, которое оказалось ужасно простым.
За всё время работы скрипта, стартует только 10 потоков, просто каждый из них, отработав со своим 1 данным, не дохнет, а берет из списка следующее 1 данное и делает с ним эту же работу:
# -*- coding: utf-8 -*-
import threading, Queue, time
import traceback
class Worker(threading.Thread):
def __init__(self,queue):
threading.Thread.__init__(self)
self.__queue = queue
def run(self):
while True:
try: item = self.__queue.get_nowait() # ждём данные
except Queue.Empty: break # данные закончились, прекращаем работу
try: self.work(item) # работа
except Exception: traceback.print_exc()
time.sleep(0.5)
self.__queue.task_done() # задача завершена
return
def work(self,item):
print item
#pass
def main():
# Выводим в 5 потоков цифры от 1 до 100.
queue = Queue.Queue()
num_threads = 5 # 5 потоков
for x in xrange(100):
queue.put(x) # заносим данные в очередь
for i in xrange(num_threads):
t = Worker(queue) # создаем поток
t.start() # стартуем
time.sleep(0.1) # чтобы в консоли друг на друга не накладывались
queue.join() #блокируем выполнение программы, пока не будут израсходованы данные.
print "Done!"
if __name__ == '__main__':
main()
И, в общем, хотелось бы еще, чтобы можно всё это в любой момент можно было бы остановить. Но поскольку мы выполнение программы блокируем с помощью queue.join(), то скрипт наши Ctr+C банально "не услышит". Я начал искать, что делать в таком случае, нашел вот такое решение, но у меня оно работало абы как. А потом, поразмыслив, я сам придумал решение, которое оказалось ужасно простым.
# -*- coding: utf-8 -*-
import threading, Queue, time
import traceback
class Worker(threading.Thread):
def __init__(self,queue):
threading.Thread.__init__(self)
self.__queue = queue
self.kill_received = False # флаг прекращения работы
def run(self):
while not self.kill_received:
try: item = self.__queue.get_nowait() # ждём данные
except Queue.Empty: break
try: self.work(item)
except Exception: traceback.print_exc()
time.sleep(0.5)
self.__queue.task_done() # задача завершена
self.__queue.put(item) # зациклим
return
def work(self,item):
print item
def main():
queue = Queue.Queue()
num_threads = 5 # 5 потоков
threads = []
for x in xrange(100):
queue.put(x) # заносим данные в очередь
for i in xrange(num_threads):
t = Worker(queue) # создаем нить
threads.append(t)
t.start() # стартуем
time.sleep(0.1)
#Пока в "живых" не останется только главный поток, ждем.
while threading.activeCount()>1:
try:
time.sleep(1)
except KeyboardInterrupt:
print "Ctrl-c received! Sending kill to threads..."
for t in threads:
t.kill_received = True # даем сигнал о завершении всем потокам
print "Done!"
if __name__ == '__main__':
main()
Подписаться на:
Сообщения (Atom)