【问题标题】:Storing a List into Python Sqlite3将列表存储到 Python Sqlite3
【发布时间】:2011-07-21 11:41:20
【问题描述】:

我正在尝试像这样使用 Beautiful Soup 来抓取表单字段 ID

 for link in BeautifulSoup(content, parseOnlyThese=SoupStrainer('input')):
    if link.has_key('id'):
        print link['id']

让我们假设它返回类似的东西

username
email
password
passwordagain
terms
button_register

我想将它写入 Sqlite3 DB。

我将在我的应用程序中做的是...使用这些表单字段的 ID 并尝试执行 POST 可能是。问题是.. 有很多这样的网站,我已经抓取了它们的表单字段 ID。所以关系是这样的……

Domain1 - First list of Form Fields for this Domain1
Domain2 - Second list of Form Fields for this Domain2
.. and so on

我不确定的是……我应该如何设计我的专栏来实现这种目的?如果我只创建一个包含两列的表可以吗 - 比如说

COL 1 - Domain URL (as TEXT)
COL 2 - List of Form Field IDs (as TEXT)

要记住的一件事是......在我的应用程序中,我需要做这样的事情......

伪代码

If Domain is "http://somedomain.com":
    For ever item in the COL2 (which is a list of form field ids):
         Assign some set of values to each of the form fields & then make a POST request

谁能指导一下?

于 2011 年 7 月 22 日编辑 - 我的以下数据库设计是否正确?

我决定采用这样的解决方案。大家觉得呢?

我将有如下三张表

表 1

Key Column (Auto Generated Integer) - Primary Key
Domain as TEXT

示例数据类似于:

1   http://url1.com
2   http://url2.com
3   http://url3.com

表 2

Domain (Here I will be using the Key Number from Table 1)
RegLink - This will have the registeration link (as TEXT)
Form Fields (as Text)

示例数据类似于:

1   http://url1.com/register    field1
1   http://url1.com/register    field2
1   http://url1.com/register    field3
2   http://url2.com/register    field1
2   http://url2.com/register    field2
2   http://url2.com/register    field3
3   http://url3.com/register    field1
3   http://url3.com/register    field2
3   http://url3.com/register    field3

表 3

Domain (Here I will be using the Key Number from Table 1)
Status (as TEXT)
User (as TEXT)
Pass (as TEXT)

示例数据类似于:

1   Pass    user1   pass1
2   Fail    user2   pass2
3   Pass    user3   pass3

你觉得这个桌子设计好不好?或者有什么可以改进的?

【问题讨论】:

    标签: python sql database sqlite


    【解决方案1】:

    您的表中存在规范化问题。

    使用2个表

    TABLE domains
    int id primary key
    text name
    
    TABLE field_ids
    int id primary key
    int domain_id foreign key ref domains
    text value
    

    是一个更好的解决方案。

    【讨论】:

    • 哦.. 所以你的意思是,在第一个表 domains 中,我将只有域 URL。而在第二个表 fields_ids 我将有类似 domain1 - field1, domain1 - field2, domain - field3, .. domain1 - fieldn ... 同样 domain2 - field1, domain2 - field2, .. domain2 ... fieldn 等。这听起来也不错。谢谢!
    • @Bhavani-Kannan:您为每个域创建一个密钥。您将它们配对在一个数据库中。然后,您将第二个数据库对中的这些键与每个字段一起使用,因为通过键查找内容比仅通过域查找要快得多。如果你想只用域名不用key,只需要一张表,可以看看我的回答。
    • 我已经用我决定做的事情编辑了我的问题。所以我打算做类似c.execute('CREATE TABLE IF NOT EXISTS base (ID INTEGER PRIMARY KEY, Domain TEXT, PR INTEGER)') c.execute('CREATE TABLE IF NOT EXISTS register (Domain INTEGER, Reglink TEXT, Fields TEXT, FOREIGN KEY(Domain) REFERENCES base(ID)') c.execute('CREATE TABLE IF NOT EXISTS regdata (Domain INTEGER, Status TEXT, Username TEXT, Password TEXT, FOREIGN KEY(Domain) REFERENCES base(ID)')的事情,你们认为这是一种优化的方式吗?
    【解决方案2】:

    正确的数据库设计建议您有一个 URL 表和一个字段表,每个都引用一个 URL 记录。但根据您想对它们做什么,您可以将列表打包成一列。见the docs for how to go about that

    sqlite 是必需的吗?这可能不是存储数据的最佳方式。例如。如果您需要通过 URL 进行随机访问查找,shelve module 可能是一个更好的选择。如果您只需要记录它们并遍历站点,则存储为 CSV 可能更简单。

    【讨论】:

    • 根本没有要求,因为我没有客户。我做这一切只是为了我在日常生活中所做的日常工作。所以,你可以说的无非就是学习。我将浏览您提供的链接。特别是我想使用 SQlite3,因为我花了几天时间学习了它的基础知识。搁置模块对我来说是新的。我会检查文件。谢谢!
    • shelve 对人们来说似乎总是很陌生。它相当有限,但如果您只需要一个键值存储(如磁盘上的字典),它就很容易使用。
    【解决方案3】:

    试试这个来获取ID:

    ids = (link['id'] for link in
            BeautifulSoup(content, parseOnlyThese=SoupStrainer('input')) 
             if link.has_key('id'))
    

    这应该向您展示如何保存它们、加载它们以及对它们做些什么。这使用一个表,并且只为每个域的每个字段插入一行。这是最简单的解决方案,完全适用于相对较少的数据行。

    from itertools import izip, repeat
    import sqlite3
    
    conn = sqlite3.connect(':memory:')
    c = conn.cursor()
    c.execute('''create table domains
    (domain text, linkid text)''')
    
    domain_to_insert = 'domain_name'
    ids = ['id1', 'id2']
    c.executemany("""insert into domains
          values (?, ?)""", izip(repeat(domain_to_insert), ids))
    conn.commit()
    
    domain_to_select = 'domain_name'
    c.execute("""select * from domains where domain=?""", (domain_to_select,))
    
    # this is just an example
    def some_function_of_row(row):
        return row[1] + ' value'
    
    fields = dict((row[1], some_function_of_row(row)) for row in c)
    print fields
    c.close()
    

    【讨论】:

    • 感谢您的回复。我只是想理解这段代码......生成器对象,izip 对我来说是新的。当我尝试执行和理解您的代码时,我正在谷歌搜索和学习。谢谢!
    • 您可以轻松地使用for 循环来获取ID,并使用另一个for 循环来插入它们(使用for id in ids: c.execute("insert into domains values (?, ?)", (domain_to_insert, id)),如果这些使事情变得更复杂并且您想集中注意力关于数据库的东西。
    • 嘿,不......没有什么让它变得复杂。就像你已经知道的那样,我是 Python 新手。才一个星期。因此,尝试收集和学习所有可能的小东西.. 就像在打印中使用 , 而不是 + 等。我只是不想要一段工作代码,而是一段健壮的代码。这就是为什么还要尝试学习和理解您的代码方式。真的,谢谢!
    • 我当然会。我只想尝试这里提供的每一个建议。一旦我最终确定了解决方案,我将更新线程并接受解决方案。谢谢!
    • 这个方案会占用大量空间,因为每个字段id都存储了域。请参阅我的解决方案如何规范化数据库模型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 1970-01-01
    相关资源
    最近更新 更多