conn = sqlite3.connect(self.__database_name)
c = conn.cursor()
sql = 'INSERT OR IGNORE INTO ' + self.__article_url_table_name + ' (url) values (%s)' % (href)
c.execute(sql)
conn.commit()
我在调用的行中收到以下错误:c.execute(sql)
sqlite3.OperationalError:near" /":语法错误
url变量是一个字符串,其中包含一个类似于:https://www.foo.com/bar.html
的网址我的代码中有什么错误?
答案 0 :(得分:5)
您不应该使用字符串插值来编写SQL查询。除了你遇到的问题之外,它让你对SQL注入开放。改为使用参数:
DayOfWeek
答案 1 :(得分:5)
错误是您没有以正确的方式使用db-api。您正在使用字符串格式构建SQL查询:
sql = "INSERT OR IGNORE INTO some_table (url) values (%s)" % href
这导致两个问题。
第一个是正确处理引用和转义。在您的情况下,您可以通过在格式符号周围添加引号来解决,例如:
sql = "INSERT OR IGNORE INTO some_table (url) values ('%s')" % href
但如果href
包含引号,这仍然会中断。
第二个也是更重要的问题是your code is now opened to sql injection attacks。
正确使用db-api将解决这两个问题:只需在sql字符串中使用dp-api模块的占位符(对于sqlite,它是'?'),并将参数传递给cursor.execute()
调用。然后你的db-api模块将负责正确的引用/转义并正确清理你的参数以防止sql注入:
sql = "INSERT OR IGNORE INTO some_table (url) values (?)"
c.execute(sql, (href,))
请注意,这不适用于表名,仅适用于传递给select,insert或delete查询的值,因此在您的情况下,您仍然必须对表名使用字符串格式:
sql = "INSERT OR IGNORE INTO {} (url) values (?)".format(self.__article_url_table_name)
c.execute(sql, (href,))
完全不相关的我注意到你对类属性使用__private
命名约定。此约定触发名称修改机制,主要用于防止意外覆盖某些属性。实际上,这几乎从来不需要(最终对于框架中的基类的某些实现细节,甚至那时)并且可能真的很烦人。 “实现属性”的约定是使用单个前导下划线,所有python程序员都将其理解为“实现细节,不要弄乱这个或者你自己”。