ValueError: неподдерживаемый символ формата в строке scrapy mysql

Я работаю над поисковым роботом scrapy, и эта проблема меня действительно беспокоит, так как я уже несколько дней был в ловушке.

Эта функция заполнителей отлично работает, когда я использую "?" вместо "% s" для SQLite db. Но при использовании "?" когда база данных переключается на MySQL, он показывает:

"TypeError: not all arguments converted during string formatting "

даже я прилагаю много усилий, изменяя коды и меняя заполнитель (предположительно?), он все равно показывает:

" query = query % self._escape_args(args, conn) ValueError: unsupported format character ',' "

более конкретно:

Traceback (most recent call last):

  File "/usr/lib64/python3.4/dist-packages/twisted/internet/defer.py", line 653, in _runCallbacks
    current.result = callback(current.result, *args, **kw)

File "/home/ec2-user/lulu_testing/get_download_file/hello_scrapy/hello/hello/pipelines.py", line 42, in process_item
    self.cur.execute(insert_query, insert_values)

File "/usr/lib/python3.4/dist-packages/pymysql/cursors.py", line 163, in execute
    query = self.mogrify(query, args)

File "/usr/lib/python3.4/dist-packages/pymysql/cursors.py", line 142, in mogrify
    query = query % self._escape_args(args, conn)

ValueError: unsupported format character ',' (0x2c) at index 94

the pipline for mysql version

import pymysql
import scrapy
from hello.items import HelloItem

class HelloPipeline(object):

def __init__(self):#

    self.conn = pymysql.connect(host = "localhost", port=3306, user = "root", passwd = "lulu", db = "test", charset = "utf8", use_unicode=True)
    self.cur = self.conn.cursor()


    self.cur.execute("drop table IF EXISTS test;")
    self.conn.commit()

    self.cur.execute("create table if not EXISTS table_test_4(test0 text, test1 text, test2 text, test3 text,test4 text, test5 text, test6 text, test7 text, test8 text, test9 text);")
    self.conn.commit()

    #pass


def process_item(self, item, spider):#

    col = ",".join(item.keys())
    placeholders = ",".join(len(item) * "%s")

    insert_query = "INSERT INTO test_table_4({0}) VALUES({1});".format(col,placeholders)

    insert_values = tuple(item.values())


    self.cur.execute(insert_query, insert_values)

    return item

def close_spider(self, spider):#
    self.cur.close()
    self.conn.close()
    #pass

the SQLite version(what i was using b4)

import sqlite3
import scrapy
from hello.items import HelloItem

class HelloPipeline(object):

def open_spider(self, spider):#
    self.conn = sqlite3.connect("test_database_ver_2018_03_31.sqlite")
    self.cur = self.conn.cursor()
    self.cur.execute("create table if not exists test_table(test0 text, test1 text, test2 text, test3 text,test4 text, test5 text, test6 text, test7 text, test8 text, test9 text);")        
    #pass

def close_spider(self, spider):#
    self.conn.commit()
    self.conn.close()
    #pass

def process_item(self, item, spider):#

    col = ",".join(item.keys())       
    placeholders = ",".join(len(item) * "?")
    sql = "insert into test_table({}) values({})"


    self.cur.execute(sql.format(col, placeholders), tuple(item.values()))


    return item

data settings of main scrapy crawler program

    testitem = HelloItem()

    testitem["test0"] = house_detail.select(".houseInfoTitle")[0].text        
    testitem["test1"] = house_detail.select(".pageView")[0].text 
    testitem["test2"] = house_detail.select(".detailInfo")[0].text
    testitem["test3"] = house_detail.select(".houseIntro")[0].text
    testitem["test4"] = house_detail.select(".lifeBox")[0].text
    testitem["test5"] = house_detail.select(".labelList")[0].text
    testitem["test6"] = house_detail.select(".facility")[0].text
    testitem["test7"] = str(house_detail.select(".userInfo"))
    testitem["test8"] = str(house_detail.select(".banner"))
    testitem["test9"] = str(house_detail.select("#show"))

    return testitem

item setting

import scrapy


class HelloItem(scrapy.Item):

test0 = scrapy.Field()
test1 = scrapy.Field()
test2 = scrapy.Field()
test3 = scrapy.Field()
test4 = scrapy.Field()
test5 = scrapy.Field()
test6 = scrapy.Field()
test7 = scrapy.Field()
test8 = scrapy.Field()
test9 = scrapy.Field()

Вы используете MS SQL Server или MySQL?

jarlh 02.05.2018 09:00

Я использую mysqld Ver 5.5.59 для Linux на x86_64 (MySQL Community Server (GPL))

meow 02.05.2018 10:15
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
2
729
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в том, что эта строка:

placeholders = ",".join(len(item) * "%s")

не делает то, что вы ожидаете.

>>> item = {'a': 1, 'b': 2, 'c': 3}
>>> placeholders = ",".join(len(item) * "%s")
>>> print(placeholders)
%,s,%,s,%,s     

",".join(len(item) * "%s") делает две вещи: вычисляет len(item) * "%s", затем объединяет результат с ','.

Результатом len(item) * '%s' является строка (или повторяемый) '%s%s%s'. str.join(iterable) возвращает строку, состоящую из всех элементов повторяемыйразделены строкой, которая предоставляет метод. Итак, результат звонка

','.join('%s%s%s') является

'%,s,%,s,%,s', а не '%s,%s,%s'

Ты хочешь сделать

>>> ",".join(len(item) * ["%s"])
'%s,%s,%s'

или же

>>> ",".join('%s' for _ in item)
'%s,%s,%s'

так что str.join работает с повторяющейся строкой '%s', а не с одной строкой, такой как '%s%s%s'. `

Большое спасибо, я только что узнал об этом. Ваше окончательное решение настолько круто, как вы могли знать, что цикл будет работать с функцией соединения и создать фантастический процесс?

meow 03.05.2018 06:13

В метод join обычно передается список строк для присоединения, поэтому, если вы не передаете ему список, вам нужно либо создать список внутри метода, например len(item) * ['%s'], либо сгенерировать поток элементов, которые будут объединены с генератором. понимание - вроде '%s' for _ in item.

snakecharmerb 03.05.2018 06:23

Я никогда не знаю, что такое применение (_ вместо _ в _) будет работать, какая в этом логика? и я обнаружил, что цикл for также будет работать с таким количеством объектов списка, как {",". join ('% s' for _ in item)} как {",". join ('% s' for _ in ( х, х, х))}

meow 03.05.2018 06:57

Это обычный способ показать, что вы на самом деле не используете переменную счетчика цикла - см. stackoverflow.com/q/5893163/5320906

snakecharmerb 03.05.2018 07:00

Другие вопросы по теме