how - Escribir elementos en una base de datos MySQL en Scrapy
scrapy media pipeline (3)
Creo que esta manera es mejor y más concisa:
#Item
class pictureItem(scrapy.Item):
topic_id=scrapy.Field()
url=scrapy.Field()
#SQL
self.save_picture="insert into picture(`url`,`id`) values(%(url)s,%(id)s);"
#usage
cur.execute(self.save_picture,dict(item))
Es como
cur.execute("insert into picture(`url`,`id`) values(%(url)s,%(id)s)" % {"url":someurl,"id":1})
Causa (puedes leer más sobre Items en Scrapy)
La clase Field es solo un alias de la clase dict incorporada y no proporciona ninguna funcionalidad o atributos adicionales. En otras palabras, los objetos de campo son simples dictados de Python.
Soy nuevo en Scrapy, tenía el código spider
class Example_spider(BaseSpider):
name = "example"
allowed_domains = ["www.example.com"]
def start_requests(self):
yield self.make_requests_from_url("http://www.example.com/bookstore/new")
def parse(self, response):
hxs = HtmlXPathSelector(response)
urls = hxs.select(''//div[@class="bookListingBookTitle"]/a/@href'').extract()
for i in urls:
yield Request(urljoin("http://www.example.com/", i[1:]), callback=self.parse_url)
def parse_url(self, response):
hxs = HtmlXPathSelector(response)
main = hxs.select(''//div[@id="bookshelf-bg"]'')
items = []
for i in main:
item = Exampleitem()
item[''book_name''] = i.select(''div[@class="slickwrap full"]/div[@id="bookstore_detail"]/div[@class="book_listing clearfix"]/div[@class="bookstore_right"]/div[@class="title_and_byline"]/p[@class="book_title"]/text()'')[0].extract()
item[''price''] = i.select(''div[@id="book-sidebar-modules"]/div[@class="add_to_cart_wrapper slickshadow"]/div[@class="panes"]/div[@class="pane clearfix"]/div[@class="inner"]/div[@class="add_to_cart 0"]/form/div[@class="line-item"]/div[@class="line-item-price"]/text()'').extract()
items.append(item)
return items
Y el código de la tubería es:
class examplePipeline(object):
def __init__(self):
self.dbpool = adbapi.ConnectionPool(''MySQLdb'',
db=''blurb'',
user=''root'',
passwd=''redhat'',
cursorclass=MySQLdb.cursors.DictCursor,
charset=''utf8'',
use_unicode=True
)
def process_item(self, spider, item):
# run db query in thread pool
assert isinstance(item, Exampleitem)
query = self.dbpool.runInteraction(self._conditional_insert, item)
query.addErrback(self.handle_error)
return item
def _conditional_insert(self, tx, item):
print "db connected-=========>"
# create record if doesn''t exist.
tx.execute("select * from example_book_store where book_name = %s", (item[''book_name'']) )
result = tx.fetchone()
if result:
log.msg("Item already stored in db: %s" % item, level=log.DEBUG)
else:
tx.execute("""INSERT INTO example_book_store (book_name,price)
VALUES (%s,%s)""",
(item[''book_name''],item[''price''])
)
log.msg("Item stored in db: %s" % item, level=log.DEBUG)
def handle_error(self, e):
log.err(e)
Después de ejecutar esto me sale el siguiente error
exceptions.NameError: global name ''Exampleitem'' is not defined
Recibí el error anterior cuando agregué el código siguiente en el método process_item
assert isinstance(item, Exampleitem)
y sin añadir esta linea estoy consiguiendo
**exceptions.TypeError: ''Example_spider'' object is not subscriptable
¿Alguien puede hacer que este código se ejecute y asegurarse de que todos los elementos se guardan en la base de datos?
Prueba el siguiente código en tu pipeline
import sys
import MySQLdb
import hashlib
from scrapy.exceptions import DropItem
from scrapy.http import Request
class MySQLStorePipeline(object):
def __init__(self):
self.conn = MySQLdb.connect(''host'', ''user'', ''passwd'',
''dbname'', charset="utf8",
use_unicode=True)
self.cursor = self.conn.cursor()
def process_item(self, item, spider):
try:
self.cursor.execute("""INSERT INTO example_book_store (book_name, price)
VALUES (%s, %s)""",
(item[''book_name''].encode(''utf-8''),
item[''price''].encode(''utf-8'')))
self.conn.commit()
except MySQLdb.Error, e:
print "Error %d: %s" % (e.args[0], e.args[1])
return item
Su método process_item se debe declarar como: def process_item(self, item, spider):
lugar de def process_item(self, spider, item):
-> cambió los argumentos.
Esta excepción: exceptions.NameError: global name ''Exampleitem'' is not defined
indica que no importó el Exampleitem a su canalización. Intente agregar: from myspiders.myitems import Exampleitem
(con nombres / rutas correctas por supuesto).