Comments 41
_GetSection не статичен, а self в аргументах заменяется на item, но при этом используется self в тексте.
if parser is not None: = if parser:
if parser is not None: = if parser:
Чем вызван выбор lxml?
А вы бы что посоветовали?
Как по мне — одна из наиболее функциональных и удобных библиотек для работы с XML. Пожалуй даже самая удобная из всех, с которыми я работал.
Как по мне — одна из наиболее функциональных и удобных библиотек для работы с XML. Пожалуй даже самая удобная из всех, с которыми я работал.
Html5lib как более универсальную обертку. Хождение по ссылкам с помощью Scrapy. Более pythonic.
Не знаю чем оно более универсальное, судя по коду (быстро пролистал) функционал там только базовый. Тем не менее, как я смотрю, html5lib в lxml уже интегрирована lxml.de/html5parser.html
Насчет Scrapy поддерживаю.
Насчет Scrapy поддерживаю.
Там кроме этого синтаксиса поддерживается синтаксис BeautifulSup и другие вкусности. Не понимаю логику минусующих.
За 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 который на гуглокоде.
хм… а до этого мы о каком html5lib говорили?
То что вы приводили — часть lxml, тот который на гуглокоде отдельный проект на сколько я понимаю.
Ну, я написал про lxml.de/html5parser.html просто чтоб показать что lxml и html5 умеет парсить.
А так да, я про гуглокодовскую говорил.
А так да, я про гуглокодовскую говорил.
Прежде всего, решением задачи. lxml дал самый быстрый отклик в плане работающего примера. Тут наверное нужно пояснить. До этого я писал полноценный скрипт на python только один раз (не считая всяких «hello world»), сам язык знаю плохо и потратил на решение задачи минимум времени (написание и отладку кода, копание в документации, сравнение различных инструментов). То есть то, что не заработало сразу или требовало длительного изучения, я отбрасывал сразу.
Смысл статьи именно в том и состоит — не похвалиться кодом, не выбрать наилучшие инструменты, а показать столь же неискушенным в теме читателям, как я, что написать работающий парсер от начала и до конца на пайтоне и с применением перечисленных средств без предварительной подготовки (изучения питоник-стиля, чтения букварей и массы документации) действительно просто. И это — лучшая реклама пайтону и использованным инструментам. Но это слова о статье.
Что касается выбора средств, то они диктовались рамками задачи. Ту же самую работу можно было без всякого программирования проделать вручную за два, много два с половиной дня. Потратить то же время на изучение различных мнений и чтение мануалов заманчиво, но при этом далеко не факт, что в результате пепелац взлетит. Словом, не обладая обширными базовыми знаниями и чутьем практика, вкладывать силы в глубокое предварительное изучение каждой претендующей на использование технологии — расточительно, когда речь идет об автоматизации решения конкретной задачи.
Что касается lxml, то он оказался простым, эффективным в плане гибкости применения, хорошо и с разных сторон документированным инструментом.
Смысл статьи именно в том и состоит — не похвалиться кодом, не выбрать наилучшие инструменты, а показать столь же неискушенным в теме читателям, как я, что написать работающий парсер от начала и до конца на пайтоне и с применением перечисленных средств без предварительной подготовки (изучения питоник-стиля, чтения букварей и массы документации) действительно просто. И это — лучшая реклама пайтону и использованным инструментам. Но это слова о статье.
Что касается выбора средств, то они диктовались рамками задачи. Ту же самую работу можно было без всякого программирования проделать вручную за два, много два с половиной дня. Потратить то же время на изучение различных мнений и чтение мануалов заманчиво, но при этом далеко не факт, что в результате пепелац взлетит. Словом, не обладая обширными базовыми знаниями и чутьем практика, вкладывать силы в глубокое предварительное изучение каждой претендующей на использование технологии — расточительно, когда речь идет об автоматизации решения конкретной задачи.
Что касается lxml, то он оказался простым, эффективным в плане гибкости применения, хорошо и с разных сторон документированным инструментом.
Используйте pastebin-ы
Статья очень похожа на курсовую работу.
Да ладно, я такое девушке постоянно пишу, когда какой-нибудь цитатник Конфуция нужно выкачать. Курсовая работа это все же посерьезнее, хотя бы на несколько недель интенсивной реализации. Не принижайте вы уж так технические вызу.
Курсовая работа — это все таки образцово-показательное выступление. Я же только брался показать, что всего за один день, со скромными познаниями в пайтоне, еще меньшим опытом и без углубления в документации и мучительный выбор, что ставить — пробелы или табуляцию (я, кстати, сразу выбрал табуляцию, просто потому что быстрее им ошибок меньше в отступах) — вполне реально решить конкретную задачу, буде такая появится.
«Чем вызван выбор lxml?» — тут вопросов нет, говорю Вам как Профессиональный Парсер. все правипльно. аналигов по скорости и адеквате нет!, но чтение статьи закончилось на первой строчке — urllib — получение HTML-страниц сайтов;, на этом Все. урл либ хорошо но при ПАРСИНГЕ соверщенно не подходит. я не говорю про проблемы с кодировкой и получением контенста, выы даже ИП не сможете нормлаьно поменять.
pycurl намного адекватный выбор.
pycurl намного адекватный выбор.
Scrapy удобно соединяет все, что нужно для web-краулинга, последующего парсинга html и сохранения результатов. Советую взглянуть в его сторону, и не изобретать велосипедов.
Поддерживаю. Хотя у меня впечатление что автор не осилит (не в обиду сказано).
Пытаюсь осилить. Однако, тут вот какая штука. Scrapy — мощный фреймворк. Он облегчает решение стандартных задач, но и устанавливает рамки. И он не подходит для первого знакомства с парсингом для таких новичков как я. Причины просты:
1. Требуется время на изучение, чтобы понять, чем именно он упрощает решение задач и как.
2. Заранее неизвестны неочевидные ограничения, которые начнут всплывать на практике и уже после того, как затрачены усилия на освоение базы.
3. Количество различных примеров и разноплановой документации для простого инструмента в несопоставимое количество раз больше, чем для фреймворка.
4. Дополнительные библиотеки, необходимые для установки. Во-первых это масса возможностей сделать ошибку. Так, например, я пытался twisted поставить на Win с помощь easy-install и все вроде бы хорошо ставилось, вот только библиотека не нашлась. Может надо было просто пути прописать к каталогу scripts, а может действительно нужно ставить через msi, но процесс на время затормозился.
4. Дополнительные библиотеки. Неминуемы отсылки документации к возможностям библиотек и время на изучение особенностей их использования во фреймворке.
В частности, сейчас я знаю (благодаря доброму совету и чтению документации по Srapy), что смог бы переписать решение задачи с использованием фреймворка. Но в очереди следующие, для решения которых нужно выбирать инструменты с оглядкой на фреймворк. Как подвесить краулер сервисом windows? Возникнут ли какие-нибудь особенности, если нужно записать данные не в файл, а в документ через API Google Docs? Можно ли вызывать Srapy из кода, а не из командной строки?
Есть и другие смутные вопросы, ответы на которые есть смысл искать, погрузившись в Srapy по самые гланды.
В любом случае, Srapy попробую. Спасибо за наводку!
1. Требуется время на изучение, чтобы понять, чем именно он упрощает решение задач и как.
2. Заранее неизвестны неочевидные ограничения, которые начнут всплывать на практике и уже после того, как затрачены усилия на освоение базы.
3. Количество различных примеров и разноплановой документации для простого инструмента в несопоставимое количество раз больше, чем для фреймворка.
4. Дополнительные библиотеки, необходимые для установки. Во-первых это масса возможностей сделать ошибку. Так, например, я пытался twisted поставить на Win с помощь easy-install и все вроде бы хорошо ставилось, вот только библиотека не нашлась. Может надо было просто пути прописать к каталогу scripts, а может действительно нужно ставить через msi, но процесс на время затормозился.
4. Дополнительные библиотеки. Неминуемы отсылки документации к возможностям библиотек и время на изучение особенностей их использования во фреймворке.
В частности, сейчас я знаю (благодаря доброму совету и чтению документации по Srapy), что смог бы переписать решение задачи с использованием фреймворка. Но в очереди следующие, для решения которых нужно выбирать инструменты с оглядкой на фреймворк. Как подвесить краулер сервисом windows? Возникнут ли какие-нибудь особенности, если нужно записать данные не в файл, а в документ через API Google Docs? Можно ли вызывать Srapy из кода, а не из командной строки?
Есть и другие смутные вопросы, ответы на которые есть смысл искать, погрузившись в Srapy по самые гланды.
В любом случае, Srapy попробую. Спасибо за наводку!
У Scrapy есть преимущество в том, что он обладает высокой поизводительностью (может качать десятки документов одновременно) и кучей готовых вспомогательных модулей, например для защиты от повторной загрузки уже загруженных страниц и зацикливания, поддержка Cookies и пр.
Есть модули для создания к нему веб-интерфейса. Есть встроенная telnet консоль (т.е. можно подключиться к запущенному и работающему пауку по telnet и выполнять внутри него любые команды Python прям во время работы). Но при этом нужно иметь в виду, что он работает асинхронно и для сохранения собранных данных в БД уже нужно изворачиваться.
Чтобы сохранить данные не в файл а в GoogleDocs тоже придется дополнительно потрудиться…
Вызвать Scrapy из кода можно, но эта возможность по-моему не документирована. Я как-то так его стартовал:
Для 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 неблокирующий а библиотека блокирующая.
Есть модули для создания к нему веб-интерфейса. Есть встроенная 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 по самые гланды».Для 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 неблокирующий а библиотека блокирующая.
Спасибо за пример! Утащил к себе в избранное.
Жаль, у меня пока нет задач, для которых действительно потребовалась бы вся мощь Scrapy (а было бы круто для приготовления холостяцкого ужина запустить промышленную установку по формированию пельменей — джастфофан).
Впрочем, думаю рано или поздно такие задачи появятся, и тогда советы придутся очень кстати.
Жаль, у меня пока нет задач, для которых действительно потребовалась бы вся мощь Scrapy (а было бы круто для приготовления холостяцкого ужина запустить промышленную установку по формированию пельменей — джастфофан).
Впрочем, думаю рано или поздно такие задачи появятся, и тогда советы придутся очень кстати.
Архив Голубятен в студию!
Ужас ужас.
Если используете lxml — используйте xpath
Почитайте про PEP8
Учитесь кодить на пайтоне, зачем здесь else?
ну и т.д.
Если используете lxml — используйте xpath
Почитайте про PEP8
Учитесь кодить на пайтоне, зачем здесь else?
if parser.group('gsource')=='Бизнес-журнале':
return 'Бизнес-журнал'
else:
return parser.group('gsource')
ну и т.д.
Хоть и не хочется обидеть, но… Похвально конечно, что боле менее разобрались и задачу решили, но статью такую лучше не показывать публично. И код тоже.
Вообще, как уже сказали, по стилю написания очень похоже на курсовую или какую-то именно студенческую работу. Типа 2 дня перед зачетом, быстренько прочитал первые 5 абзацев из каждого мануала и начал строчить статью с как можно большим наборов умных слов и растянутыми предложениями… Это уж очень в глаза бросается.
По коду:
* все-таки не понимаю зачем XPath вынесли в конфиг… SQL запросы в своих программах тоже в конфиг будете выносить?
* лесенки из if — это как-то очень подозрительно…
* вместо
* писать
* строки кода длиннее 80 символов не рекомендуются. Если пишите цепочку функций, лучше переносите на след. строку, обернув в скобки:
* генерировать CSV вручную — последнее дело. Есть специальный модуль, встроенный в Python docs.python.org/library/csv.html
* вместо
пишем
*
* Хранить ВСЕ скачанные материалы в памяти (
* Везде по коду натыканы
* Склеивать строки сложением (+) считается дурным тоном. Но тут есть варианты.
Можно и дальше продолжать в принципе…
Вообще, как уже сказали, по стилю написания очень похоже на курсовую или какую-то именно студенческую работу. Типа 2 дня перед зачетом, быстренько прочитал первые 5 абзацев из каждого мануала и начал строчить статью с как можно большим наборов умных слов и растянутыми предложениями… Это уж очень в глаза бросается.
По коду:
* все-таки не понимаю зачем XPath вынесли в конфиг… SQL запросы в своих программах тоже в конфиг будете выносить?
* лесенки из if — это как-то очень подозрительно…
* вместо
if len(src)==0
можно писать if not src:
и т.п.* писать
if condition: do smth
(if и тело подвыражения на одной строке) хоть и можно, но очень не рекомендуется* строки кода длиннее 80 символов не рекомендуются. Если пишите цепочку функций, лучше переносите на след. строку, обернув в скобки:
m.synopsis = get_text(item,cfg['sgolub']['list']['xpath_synopsis']).strip('\n').replace('\n',u' ').replace(';',u'|').strip().encode('utf-8')
заменяем наm.synopsis = (
get_text(item,cfg['sgolub']['list']['xpath_synopsis'])
.strip('\n')
.replace('\n',u' ')
.replace(';',u'|')
.strip()
.encode('utf-8'))
* генерировать CSV вручную — последнее дело. Есть специальный модуль, встроенный в Python docs.python.org/library/csv.html
* вместо
fdoc = open(fname, 'w')
fdoc.write(m.text)
fdoc.close()
пишем
with open(fname, 'w') as fdoc:
fdoc.write(m.text)
— после выхода из with или если случится Exception файл закроется автоматически. Файловые дескрипторы гарантированно не утекают*
self.mlist+=[m]
заменяем на self.mlist.append(m)
* Хранить ВСЕ скачанные материалы в памяти (
self.mlist
) не рационально. Лучше записывать в файл сразу после распарсивания очередной статьи. yield
вам в помощь. Хотя тут много уже переписывать придется.* Везде по коду натыканы
.encode('utf-8')
.encode('cp1251')
. Может названия кодировок в конфиг вынести? Да и внутри программы лучше юникодом пользоваться (в Python юникод != utf8).* Склеивать строки сложением (+) считается дурным тоном. Но тут есть варианты.
Можно и дальше продолжать в принципе…
Можно и дальше продолжать в принципе…
Так вы продолжайте не стесняйтесь, между прочим очень интересно и автору подозреваю тоже, как вы говорите надо склеивать строки?
Спасибо за развернутые и полезные комментарии. Для того, чтобы узнать многое из описанного, потребовалось бы кипу всего перечитать. Например, сам никогда бы не задался вопросом, есть ли специальный модуль для записи CSV-файлов!
С кодировками вышла самая большая маета, осмыслить проблему логически не получилось и пришлось подбирать методом тыка. Наверное как раз из-за того, что в Python юникод != utf8.
С выносом XPath в конфиг все просто (кстати, да SQL я бы тоже вынес). Говорят, что человек, начинающий изучать два иностранных языка, путает слова и конструкции и только с опытом происходит надежное отделение двух языковых полей. Так и здесь: ХPath запросы, помещенные прямо в текст, отвлекали от кода. Кроме того, оказалось удобнее отделить написание python-кода, и отладку XPath. Охотно признаю, что опыт в том и другом сделает такое разделение избыточным.
По хранению в памяти согласен. Но в данной задаче памяти требовалось немного, а отлаживать отдельно парсинг и запись в файл показалось удобнее. На других объемах, разумеется, пришлось бы память экономить.
С кодировками вышла самая большая маета, осмыслить проблему логически не получилось и пришлось подбирать методом тыка. Наверное как раз из-за того, что в Python юникод != utf8.
С выносом XPath в конфиг все просто (кстати, да SQL я бы тоже вынес). Говорят, что человек, начинающий изучать два иностранных языка, путает слова и конструкции и только с опытом происходит надежное отделение двух языковых полей. Так и здесь: ХPath запросы, помещенные прямо в текст, отвлекали от кода. Кроме того, оказалось удобнее отделить написание python-кода, и отладку XPath. Охотно признаю, что опыт в том и другом сделает такое разделение избыточным.
По хранению в памяти согласен. Но в данной задаче памяти требовалось немного, а отлаживать отдельно парсинг и запись в файл показалось удобнее. На других объемах, разумеется, пришлось бы память экономить.
>> Notepad++ — текстовый редактор с подсветкой синтаксиса:
SciTE(http://code.google.com/p/scite-ru/) лучше)
SciTE(http://code.google.com/p/scite-ru/) лучше)
Еще раз спасибо всем за обсуждение, советы и замечания!
Узнал много нового и полезного, как из комментариев, так и благодаря им. Жаль, что не могу проголосовать, не ожидал, что время голосования истекает.
Узнал много нового и полезного, как из комментариев, так и благодаря им. Жаль, что не могу проголосовать, не ожидал, что время голосования истекает.
Sign up to leave a comment.
Парсинг на Pуthon. Как собрать архив Голубятен