Да уж, реализация «БД» там адская. При подсоединении более одного клиента одновременно будет race-condition. Ну и вся база целиком в память считывается.
В общем, для 10-100 клиентов еще можно поюзать, больше — начнутся проблемы.
Гы-гы… А они меня недавно приглашали на работу)) Я даже на собеседование сходил из интереса. Они какую-то «принципиально-новую» платежную систему собирались создавать… На PHP…
О как… А если там такая жесть, то что же тогда называли Garbage Collector тут www.php.net/ChangeLog-5.php#5.3.0
«Added garbage collector. (David Wang, Dmitry).»?
Макс, кстати… Пользуясь случаем — ты в ЖЖ пару месяцев назад писал, что планируешь написать статью о том как правильно строить OTP приложения. Стоит ждать статью то?
Про DBus интересно было бы. Использовал его пару раз из Python и из консоли через qdbus, но не сильно вникал в подробности. В частности интересно — DBus где-то кроме десктопа актуален? Как у него с ограничением прав доступа?
А в статье хотелось бы еще видеть рекомендации что в каких случаях лучше применять…
У Scrapy есть преимущество в том, что он обладает высокой поизводительностью (может качать десятки документов одновременно) и кучей готовых вспомогательных модулей, например для защиты от повторной загрузки уже загруженных страниц и зацикливания, поддержка Cookies и пр.
Есть модули для создания к нему веб-интерфейса. Есть встроенная telnet консоль (т.е. можно подключиться к запущенному и работающему пауку по telnet и выполнять внутри него любые команды Python прям во время работы). Но при этом нужно иметь в виду, что он работает асинхронно и для сохранения собранных данных в БД уже нужно изворачиваться.
Чтобы сохранить данные не в файл а в GoogleDocs тоже придется дополнительно потрудиться…
Вызвать Scrapy из кода можно, но эта возможность по-моему не документирована. Я как-то так его стартовал:
""" run as `python this_file.py <spider_name> <start_url>` """
import os
os.environ.setdefault('SCRAPY_SETTINGS_MODULE', 'forums.settings')
import sys
from scrapy.core.queue import ExecutionQueue
from scrapy.core.manager import scrapymanager
from scrapy.spider import spiders
import scrapy_syslog_log as syslog_log
def main():
syslog_log.patch()
scrapymanager.configure(control_reactor=True)
q=ExecutionQueue()
spider_name, url=get_spider_and_url()
spider=spiders.create(spider_name)
q.append_url(spider.getFetchUrl(url), spider)
scrapymanager.queue=q
scrapymanager.start()#this is blocking call
sys.stdout.write('OK')
sys.exit(0)
def get_spider_and_url():
if len(sys.argv)<3:
sys.stdout.write('ERR')
sys.exit('NOT ALL ARGS')
return sys.argv[1:]
if __name__=='__main__':
main()
Чтоб этот кусок кода написать, пришлось «погрузиться в Srapy по самые гланды».
Для начала, XSLT может быть и не только шаблонизатором, это не совсем то же что и Smarty/HAML. Ну да ладно.
Доводилось работать с Smarty, Django шаблонами, mako шаблонами, просто PHP тоже само собой… Из всего этого XSLT оставил наиболее приятные впечатления. Хотя Django и Mako тоже ничего, но Django слишком простой, приходится кастомные теги клепать а mako позволяет как PHP вставлять любой питоний код в шаблон, что опасно.
// да, можно и в plain text, но в большинстве случаев из XML в XML/HTML.
Честно говоря, хотелось бы это обсуждение закончить т.к. к единому мнению вряд-ли придем))
Хоть и не хочется обидеть, но… Похвально конечно, что боле менее разобрались и задачу решили, но статью такую лучше не показывать публично. И код тоже.
Вообще, как уже сказали, по стилю написания очень похоже на курсовую или какую-то именно студенческую работу. Типа 2 дня перед зачетом, быстренько прочитал первые 5 абзацев из каждого мануала и начал строчить статью с как можно большим наборов умных слов и растянутыми предложениями… Это уж очень в глаза бросается.
По коду:
* все-таки не понимаю зачем XPath вынесли в конфиг… SQL запросы в своих программах тоже в конфиг будете выносить?
* лесенки из if — это как-то очень подозрительно…
* вместо if len(src)==0 можно писать if not src: и т.п.
* писать if condition: do smth (if и тело подвыражения на одной строке) хоть и можно, но очень не рекомендуется
* строки кода длиннее 80 символов не рекомендуются. Если пишите цепочку функций, лучше переносите на след. строку, обернув в скобки:
— после выхода из with или если случится Exception файл закроется автоматически. Файловые дескрипторы гарантированно не утекают
* self.mlist+=[m] заменяем на self.mlist.append(m)
* Хранить ВСЕ скачанные материалы в памяти (self.mlist) не рационально. Лучше записывать в файл сразу после распарсивания очередной статьи. yield вам в помощь. Хотя тут много уже переписывать придется.
* Везде по коду натыканы .encode('utf-8').encode('cp1251'). Может названия кодировок в конфиг вынести? Да и внутри программы лучше юникодом пользоваться (в Python юникод != utf8).
* Склеивать строки сложением (+) считается дурным тоном. Но тут есть варианты.
За 10 минут сложилось такое впечатление: Документации нет. Что умеет не понятно. Написана целиком на Pyhton — скорее всего медленнее и памяти больше надо. Умеет ли XPath — не понятно. Умеет ли CSS селекторы — не ясно. Чем универсальнее — тоже не совсем понимаю. Может пример небольшой дадите?
Например спарсить топик и его метаданные с хабра:
import urllib # urllib для краткости примера. Обычно Scrapy или celery.
from lxml import etree
topic={}
tree=etree.HTML(urllib.urlopen('http://habrahabr.ru/blogs/python/121815/').read())
_topic_block=tree.cssselect("div.hentry")[0]
topic['title']=_topic_block.xpath("h2/span[@class='topic']/text()")[0]
topic['body']=etree.tounicode(_topic_block.xpath("div[@class='content']")[0])
topic['tags']=_topic_block.xpath("ul[@class='tags']/li/a/text()")
topic['author']=_topic_block.cssselect("a.nickname")[0].xpath("span/text()")[0]
При этом я обычно использую пару своих функций — расширений для XPath чтобы проще @class обрабатывать и не использую CSS селекторы. Тут уж совсем для краткости сделал.
По поводу минуса — это я сгоряча. А карму плюсанул для равновесия.
Не знаю чем оно более универсальное, судя по коду (быстро пролистал) функционал там только базовый. Тем не менее, как я смотрю, html5lib в lxml уже интегрирована lxml.de/html5parser.html
В общем, для 10-100 клиентов еще можно поюзать, больше — начнутся проблемы.
«Added garbage collector. (David Wang, Dmitry).»?
А в статье хотелось бы еще видеть рекомендации что в каких случаях лучше применять…
Есть модули для создания к нему веб-интерфейса. Есть встроенная telnet консоль (т.е. можно подключиться к запущенному и работающему пауку по telnet и выполнять внутри него любые команды Python прям во время работы). Но при этом нужно иметь в виду, что он работает асинхронно и для сохранения собранных данных в БД уже нужно изворачиваться.
Чтобы сохранить данные не в файл а в GoogleDocs тоже придется дополнительно потрудиться…
Вызвать Scrapy из кода можно, но эта возможность по-моему не документирована. Я как-то так его стартовал:
Чтоб этот кусок кода написать, пришлось «погрузиться в Srapy по самые гланды».
Для GoogleDocs попробуйте официальную библиотеку от Google code.google.com/p/gdata-python-client/.
Вот примеры: code.google.com/p/gdata-python-client/source/browse/samples/docs/docs_example.py code.google.com/p/gdata-python-client/source/browse/samples/docs/resumable_upload_sample.py
Но со Scrapy ее будет не очень легко интегрировать. Разве что пул потоков организовать т.к. Scrapy неблокирующий а библиотека блокирующая.
Или им помимо самого фреймворка нужно еще и таск-трекер написать?))
или
Доводилось работать с Smarty, Django шаблонами, mako шаблонами, просто PHP тоже само собой… Из всего этого XSLT оставил наиболее приятные впечатления. Хотя Django и Mako тоже ничего, но Django слишком простой, приходится кастомные теги клепать а mako позволяет как PHP вставлять любой питоний код в шаблон, что опасно.
// да, можно и в plain text, но в большинстве случаев из XML в XML/HTML.
Честно говоря, хотелось бы это обсуждение закончить т.к. к единому мнению вряд-ли придем))
Вообще, как уже сказали, по стилю написания очень похоже на курсовую или какую-то именно студенческую работу. Типа 2 дня перед зачетом, быстренько прочитал первые 5 абзацев из каждого мануала и начал строчить статью с как можно большим наборов умных слов и растянутыми предложениями… Это уж очень в глаза бросается.
По коду:
* все-таки не понимаю зачем XPath вынесли в конфиг… SQL запросы в своих программах тоже в конфиг будете выносить?
* лесенки из if — это как-то очень подозрительно…
* вместо
if len(src)==0
можно писатьif not src:
и т.п.* писать
if condition: do smth
(if и тело подвыражения на одной строке) хоть и можно, но очень не рекомендуется* строки кода длиннее 80 символов не рекомендуются. Если пишите цепочку функций, лучше переносите на след. строку, обернув в скобки:
заменяем на
* генерировать CSV вручную — последнее дело. Есть специальный модуль, встроенный в Python docs.python.org/library/csv.html
* вместо
пишем
— после выхода из with или если случится Exception файл закроется автоматически. Файловые дескрипторы гарантированно не утекают
*
self.mlist+=[m]
заменяем наself.mlist.append(m)
* Хранить ВСЕ скачанные материалы в памяти (
self.mlist
) не рационально. Лучше записывать в файл сразу после распарсивания очередной статьи.yield
вам в помощь. Хотя тут много уже переписывать придется.* Везде по коду натыканы
.encode('utf-8')
.encode('cp1251')
. Может названия кодировок в конфиг вынести? Да и внутри программы лучше юникодом пользоваться (в Python юникод != utf8).* Склеивать строки сложением (+) считается дурным тоном. Но тут есть варианты.
Можно и дальше продолжать в принципе…
Например спарсить топик и его метаданные с хабра:
При этом я обычно использую пару своих функций — расширений для XPath чтобы проще @class обрабатывать и не использую CSS селекторы. Тут уж совсем для краткости сделал.
По поводу минуса — это я сгоряча. А карму плюсанул для равновесия.
А так да, я про гуглокодовскую говорил.
Насчет Scrapy поддерживаю.
Как по мне — одна из наиболее функциональных и удобных библиотек для работы с XML. Пожалуй даже самая удобная из всех, с которыми я работал.