将字典中的值插入sqlite数据库

时间:2014-07-31 00:57:55

标签: python database sqlite

我无法理解它。 我想将字典的值插入到sqlite数据库中。

url = "https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=5f...1b&per_page=250&accuracy=1&has_geo=1&extras=geo,tags,views,description"
soup = BeautifulSoup(urlopen(url)) #soup it up
for data in soup.find_all('photo'): #parsing the data
    dict = { #filter the data, find_all creats dictionary KEY:VALUE
        "id_p": data.get('id'),
        "title_p": data.get('title'),
        "tags_p": data.get('tags'),
        "latitude_p": data.get('latitude'),
        "longitude_p": data.get('longitude'),
    }
    #print (dict)
    connector.execute("insert into DATAGERMANY values (?,?,?,?,?)", );
    connector.commit()

connector.close

我的密钥是id_ptitle_p等,以及我通过data.get检索的值。

但是,我无法插入它们。 当我尝试在id, title, tags, latitude, longitude后面写...DATAGERMANY values (?,?,?,?,?)", );时,我得到了 NameError: name 'title' is not defined

我使用dict.valuesdict进行了尝试,但后来却说table DATAGERMANY has 6 columns but 5 values were supplied

添加另一个?会给我错误(带有'dict.values):ValueError:参数属于不支持的类型

这就是我创建数据库和表的方法。

#creating SQLite Database and Table
connector = sqlite3.connect("GERMANY.db") #create Database and Table, check if NOT NULL is a good idea
connector.execute('''CREATE TABLE DATAGERMANY
        (id_db INTEGER PRIMARY KEY AUTOINCREMENT,
        id_photo INTEGER NOT NULL,
        title TEXT,
        tags TEXT,
        latitude NUMERIC NOT NULL, 
        longitude NUMERIC NOT NULL);''')

即使没有value填入数据库,该方法也应该有效......也可能发生这种情况。

3 个答案:

答案 0 :(得分:7)

您可以使用命名参数并使用executemany()一次插入所有行。

作为奖励,你可以很好地分离html解析和数据流水线逻辑:

data = [{"id_p": photo.get('id'),
         "title_p": photo.get('title'),
         "tags_p": photo.get('tags'),
         "latitude_p": photo.get('latitude'),
         "longitude_p": photo.get('longitude')} for photo in soup.find_all('photo')]
connector.executemany("""
    INSERT INTO
        DATAGERMANY
        (id_photo, title, tags, latitude, longitude)
    VALUES
        (:id_p, :title_p, :tags_p, :latitude_p, :longitude_p)""", data)

另外,不要忘记实际调用close()方法:

connector.close()

仅供参考,完整的代码:

import sqlite3
from urllib2 import urlopen
from bs4 import BeautifulSoup

url = "https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=5f...1b&per_page=250&accuracy=1&has_geo=1&extras=geo,tags,views,description"
soup = BeautifulSoup(urlopen(url))

connector = sqlite3.connect(":memory:")
cursor = connector.cursor()

cursor.execute('''CREATE TABLE DATAGERMANY
        (id_db INTEGER PRIMARY KEY AUTOINCREMENT,
        id_photo INTEGER NOT NULL,
        title TEXT,
        tags TEXT,
        latitude NUMERIC NOT NULL,
        longitude NUMERIC NOT NULL);''')

data = [{"id_p": photo.get('id'),
         "title_p": photo.get('title'),
         "tags_p": photo.get('tags'),
         "latitude_p": photo.get('latitude'),
         "longitude_p": photo.get('longitude')} for photo in soup.find_all('photo')]

cursor.executemany("""
    INSERT INTO
        DATAGERMANY
        (id_photo, title, tags, latitude, longitude)
    VALUES
        (:id_p, :title_p, :tags_p, :latitude_p, :longitude_p)""", data)

connector.commit()

cursor.close()
connector.close()

答案 1 :(得分:4)

如上所述,您的connector.execute()语句缺少parameters参数。

它应该像这样使用:

connector.execute("insert into some_time values (?, ?)", ["question_mark_1", "question_mark_2"])

除非您以后需要字典,否则我实际上会使用列表或元组:

row = [
  data.get('id'),
  data.get('title'),
  data.get('tags'),
  data.get('latitude'),
  data.get('longitude'),
]

然后你的插入语句变为:

connector.execute("insert into DATAGERMANY values (NULL,?,?,?,?,?)", *row)

为什么要改变这些?

  • NULL中的values (NULL, ...)是自动递增的主键可以使用
  • 列表而非字典,因为订单很重要,字典不会保留订单
  • *row因此将展开五元素row变量(有关详细信息,请参阅here)。
  • 最后,您不应该使用dict作为变量名称,因为它是Python中的内置变量。

答案 2 :(得分:0)

如果您使用的是Python 3.6或更高版本,则可以执行以下操作:

dict_data = {
 'filename' : 'test.txt',
 'size' : '200'
}
table_name = 'test_table'
attrib_names = ", ".join(dict_data.keys())
attrib_values = ", ".join("?" * len(dict_data.keys()))
sql = f"INSERT INTO {table_name} ({attrib_names}) VALUES ({attrib_values})"
cursor.execute(sql, list(dict_data.values()))