MySQLdb 和 Scrapy:INSERT INTO 错误

0 投票
3 回答
517 浏览
提问于 2025-04-18 11:38

我正在尝试使用 Scrapy 和 MySQLdb 的 INSERT INTO 命令,把抓取到的数据放入本地的 MySQL 数据库里。我已经花了好几天在研究这个,但还没有找到解决办法。我希望有人能帮我理解我哪里做错了,因为我对 Python 还很陌生。

这是 spider.py 的内容:

from scrapy.selector import Selector
from scrapy.contrib.spiders import CrawlSpider
from scrapy.log import *
from folketing_crawler.settings import *
from folketing_crawler.items import FolketingCrawlerItem

class FolketingSpider(CrawlSpider):
    name = 'ft2'
    allowed_domains = ["ft.dk"]
    start_urls = ["http://www.ft.dk/Dokumenter/Vis_efter_type/Beslutningsforslag.aspx?session=&caseStatus=-1&ministerArea=-1&committee=&proposedBy=1&startDate=20110915&endDate=20140421&dateRelatedActivity=100242%2f200049&sortColumn=&sortOrder=&startRecord=&totalNumberOfRecords=&numberOfRecords=999&pageNr=#dok"]

    def parse(self, response):
        sel = Selector(response)
        item = FolketingCrawlerItem()
        item['nr'] = sel.xpath('/html/body/form/div[3]/div/div[2]/div[5]/div/div/table/tbody/tr/td[1]/text()').extract()
        return item

这是 pipelines.py 的内容:

import sys
import MySQLdb
import MySQLdb.cursors
import hashlib
from scrapy.exceptions import DropItem
from scrapy.http import Request
from scrapy.item import Item, Field

class FolketingCrawlerPipeline(object):
    def process_item(self, item, spider):
        db = MySQLdb.connect(user='root', passwd='password', db='ftdb', host='localhost', charset="utf8", use_unicode=True)
        cursor = db.cursor()  
        cursor.execute("INSERT INTO employees (hire_date) VALUES (%s)", item['nr'])
        db.commit()

        print "INSERT was successful"
        return item

这是 items.py 的内容:

from scrapy.item import Item, Field

class FolketingCrawlerItem(Item):
    nr = Field()

在 settings.py 中,我添加了这些内容来调用管道:

ITEM_PIPELINES = {
    'folketing_crawler.pipelines.FolketingCrawlerPipeline': 500
}

看起来 pipeline.py 中的 "cursor.execute" 有问题,但我在网上找了各种不同的写法来尝试,包括:

cursor.execute("INSERT INTO employees (hire_date) VALUES (%s)", item['nr'])
cursor.execute("""INSERT INTO employees (hire_date) VALUES (%s)""", item['nr'])
cursor.execute("INSERT INTO employees (hire_date) VALUES (%s)", (item['nr']))
cursor.execute("INSERT INTO employees (hire_date,) VALUES (%s,)", (item['nr'],))
cursor.execute("INSERT INTO employees (hire_date) VALUES (%s)", str(item['nr'])

我尝试了所有可能的组合,但也许问题出在 spider 里,数据存储在 item['nr'] 里?当我运行这个 scrapy 项目时,收到了以下错误:

exceptions.TypeError: not all arguments converted during string formatting

希望有人能帮我解决这个问题。我需要把数据列表存储在一行里,这样每一“条”数据都能在表格的新行中。

提前谢谢大家。

3 个回答

0

hire_date 看起来像是一个 SQL 时间戳。你可以给它一个 Python 的 datetime 对象,像这样:

cursor.execute("INSERT INTO employees (hire_date) VALUES (?)", (datetime.datetime.now(),) )

注意:execute 方法总是需要一个参数,通常是一个元组。参考链接:https://docs.python.org/2/library/sqlite3.html#sqlite3.Cursor.execute

0

我觉得

item['nr'] = sel.xpath('/html/body/form/div[3]/div/div[2]/div[5]/div/div/table/tbody/tr/td[1]/text()').extract()

返回一个元组,你试过直接获取第一个元素吗?

item['nr'] = sel.xpath('/html/body/form/div[3]/div/div[2]/div[5]/div/div/table/tbody/tr/td[1]/text()').extract()[0]
0

在 scrapy shell 会话中检查时,

$ scrapy shell "http://www.ft.dk/Dokumenter/Vis_efter_type/Beslutningsforslag.aspx?session=&caseStatus=-1&ministerArea=-1&committee=&proposedBy=1&startDate=20110915&endDate=20140421&dateRelatedActivity=100242%2f200049&sortColumn=&sortOrder=&startRecord=&totalNumberOfRecords=&numberOfRecords=999&pageNr=#dok"
2014-07-01 01:29:28+0200 [scrapy] INFO: Scrapy 0.24.1 started (bot: scrapybot)
...
sel.xpath('/html/body/form/div[3]/div/div[2]/div[5]/div/div/table/tbody/tr/td[1]/text()').extract()
Out[1]: 
[u'B 2',
 u'B 3',
 u'B 4',
 u'B 5',
 u'B 6',
...
 u'B 88',
 u'B 89',
 u'B 90',
 u'B 91',
 u'B 92',
 u'B 93']

In [2]: 

如果你想把上面列表中的每个元素都存储为一行,可能应该使用类似下面的方式:

cursor.executemany("INSERT INTO employees (hire_date) VALUES (%s)",
                   [(nr,) for nr in item['nr']])

撰写回答