web-dev-qa-db-fra.com

Écriture d'éléments dans une base de données MySQL dans Scrapy

Je suis nouveau sur Scrapy, j'avais le code araignée

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

Et le code du pipeline est:

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)          

Après avoir exécuté cela, j'obtiens l'erreur suivante

exceptions.NameError: global name 'Exampleitem' is not defined

J'ai eu l'erreur ci-dessus lorsque j'ai ajouté le code ci-dessous dans process_item méthode

assert isinstance(item, Exampleitem)

et sans ajouter cette ligne, je reçois

**exceptions.TypeError: 'Example_spider' object is not subscriptable

Quelqu'un peut-il exécuter ce code et s'assurer que tous les éléments sont enregistrés dans la base de données?

20

Essayez le code suivant dans votre 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

Je pense que cette façon est meilleure et plus concise:

#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))

C'est comme

cur.execute("insert into picture(`url`,`id`) values(%(url)s,%(id)s)" % {"url":someurl,"id":1})

Cause (vous pouvez en savoir plus sur Items in Scrapy)

La classe Field n'est qu'un alias de la classe dict intégrée et ne fournit aucune fonctionnalité ni attribut supplémentaires. En d'autres termes, les objets Field sont anciens Python dicts.

1
FavorMylikes

Votre méthode process_item doit être déclarée comme suit: def process_item(self, item, spider): au lieu de def process_item(self, spider, item): -> vous avez inversé les arguments.

Cette exception: exceptions.NameError: global name 'Exampleitem' is not defined indique que vous n'avez pas importé le Exampleitem dans votre pipeline. Essayez d'ajouter: from myspiders.myitems import Exampleitem(avec les noms/chemins corrects des cours).

1
Sjaak Trekhaak