psycopg2 - 列出超出 html大字符串字段范围的索引

问题描述

我有一个网络爬虫,它应该将 html 页面内容保存/插入到带有一些其他元数据字段的 Postgresql 数据库中。

使用 mogrify 插入 html 内容字段时,我会收到错误消息 List index out of range。如果我对 html 内容使用静态虚拟文本,例如“Hello World ö ü ä ß”(我正在处理德语字符集)插入工作正常。

这是我的功能

def batch_insert(df,table,no_cols,conn=None,upsert_qry=""):
    """
    Using cursor.mogrify() to build the bulk insert query
    then cursor.execute() to execute the query
    """
    if conn is None:
        conn = get_connection()

    col_str = "(" + (no_cols-1)*"%s," + "%s)"
    # Create a list of tuples from the dataframe values
    tuples = [tuple(x) for x in df.to_numpy()]
    # Comma-separated dataframe columns
    cols = ','.join(list(df.columns))
    # sql quert to execute
    cursor = conn.cursor()

    values = [cursor.mogrify(col_str,tup).decode('utf8') for tup in tuples]

    query = "INSERT INTO %s(%s) VALUES " % (table,cols) + ",".join(values) + upsert_qry
        #" ON CONFLICT (hk_portal_pid) DO UPDATE SET crawled_last=" + str(datetime.Now())
        
    try:
        cursor.execute(query,tuples)
        conn.commit()
    except (Exception,psycopg2.DatabaseError) as error:
        print("Error: %s" % error)
        conn.rollback()
        cursor.close()
        return 1
    print("execute_mogrify() done")
    cursor.close()
    conn.close()

按照this post 中的建议,postgres 列字段声明为text。在我的案例中,html 内容的平均长度为 40.000 个字符,因此不应该有任何存储问题。

我还检查了函数生成元组是否因转义字符等原因被拆分为 html 内容字段。但似乎并非如此。

>>>>[len(a) for a in tuples]
    [9,9,9] # 4 rows / 9 columns

第 8 列(page_content)的数据类型是字符串:

>>>>type(tuples[0][7])
<class 'str'>

批量插入的目标表:

CREATE TABLE public.as_portal_parent_content (
    hk_page varchar(100) NULL,hk_offer varchar(100) NULL,portal_id varchar(3) NULL,pid varchar(10) null,page_category varchar(30) null,page_link bpchar(300) null,status varchar(3) null,page_content text null,last_crawled timestamp null
);

非常感谢任何帮助!

添加/编辑:

追溯:

Traceback (most recent call last):
  File "C:/Users/PycharmProjects/pythonProject/project/playground.py",line 5,in <module>
    test.save_to_db(table='as_portal_parent_content')
  File "C:/Users/PycharmProjects/pythonProject/project/util/crawl.py",line 163,in save_to_db
    batch_insert(self.df,table)
  File "C:/Users/PycharmProjects/pythonProject/project/util/db.py",line 60,in batch_insert
    cursor.execute(query,tuples)
IndexError: list index out of range

Process finished with exit code 1

解决方法

您不应在 tuples 中使用 cursor.execute(query,tuples)
当您使用 mogrify 时,您基本上是在生成 sql 查询的 after-VALUES 部分。因此,无需再次将查询参数(在您的情况下为 tuples)传递给 cur.execute