yarkov
@yarkov
Помог ответ? Отметь решением.

Как выполнить действие после yield?

# -*- coding: utf-8

import MySQLdb
from grab.spider import Spider, Task
import logging
import time
import re
import urllib2

def _ru(s="", e='utf-8'):
	try:
		s = s.encode(e)
	except:
		return s
	return s

class BashImSpider(Spider):

	host = "localhost"
	user = "root"
	passwd = ""
	base = "bashorg"
	charset = 'utf8'
	initurl = 'http://bash.im/'
	user_agent = (
		"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:30.0) Gecko/20100101 Firefox/30.0"
	)
	currentPage = 1

	root = '//div[@class="quote"]'
	id = './/a[@class="id"]'
	cite = './/div[@class="text"]'

	def __init__(self):
		super(self.__class__, self).__init__()
		self.db = MySQLdb.connect(
									host=self.host, 
									user=self.user, 
									passwd=self.passwd, 
									db=self.base, 
									charset=self.charset
								)
		self.cursor = self.db.cursor()
		self.maxPage = self.getMaxPage()

	def task_generator(self):
		"""Проходим в цикле по всем страницам и генерируем задачи для парсера Spider"""
		# здесь цикл по количеству страниц, а после цикла закрыть соединение с БД
		while self.currentPage < self.maxPage:
			url = self.getUrl(self.currentPage)
			self.currentPage = self.currentPage + 1
			yield Task('search', url=url)

		# А ТУТ НАДО КАК-ТО ЗАКРЫТЬ КОННЕКТ К БД, НО ЭТО ДЕЙСТВИЕ НЕ ВЫПОЛНЯЕТСЯ!!!
		self.db.close()

	def getUrl(self, page):
		"""Вернет URL страницы в формате http://bash.im/index/%номер страницы%"""
		return  "%sindex/%s" % (self.initurl, str(page))

	def getMaxPage(self):
		"""Вернет число страниц для построения цикла"""
		req = urllib2.Request(
			url=self.initurl,
			headers={"User-Agent": self.user_agent}
		)
		page = urllib2.urlopen(req)
		data = page.read()
		result = re.search(r'max=\"([0-9]+)\"', _ru(data.decode('windows-1251')))
		return int(result.group(1))

	def writeCitate(self, sqlData = ()):
		"""Заносим цитаты в БД"""
		sql = "INSERT INTO bash (quote_id, quote_text) VALUES ({quote_id}, '{quote_text}')".format(
																										quote_id = str(sqlData[0]), 
																										quote_text = str(sqlData[1])
																									)
		self.cursor.execute(sql)
		self.db.commit()

	def task_search(self, grab, task):
		"""Собираем все цитаты со страницы"""
		for elem in grab.doc.select(self.root):
			time.sleep(1)
			try:
				id = elem.select(self.id)
				cite = elem.select(self.cite)
				sqlData = (
						id.number(),
						_ru(cite.html()
							.replace( '<div class="text">', '' )
							.replace( '</div>', '' ))
						)
				self.writeCitate(sqlData)
			except:
				continue


logging.basicConfig(level=logging.DEBUG)
bashParser = BashImSpider()
bashParser.run()


Как сделать чтобы метод self.db.close() все-таки вызвался?
  • Вопрос задан
  • 382 просмотра
Решения вопроса 2
abs0lut
@abs0lut
Воспользуйтесь контекстным менеджером with
Ответ написан
Комментировать
@nirvimel
try:
    while condition:
        yield something
finally:
    db.close()

И замените это
except:
    continue
на
except StandardError:
    continue
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы