Ошибка синтаксиса SQL конвейера Scrapy
У меня есть паук, который берет URL-адреса из БД MySQL и использует их в качестве start_urls для очистки, который, в свою очередь, захватывает любое количество новых ссылок с очищенных страниц. Когда я устанавливаю конвейер на INSERT и start_url, и новый очищенный URL-адрес на новую БД, или когда я устанавливаю конвейер на ОБНОВЛЕНИЕ существующей БД с недавно очищенными URL-адресами, используя start_url в качестве критерия WHERE, я получаю ошибку синтаксиса SQL.
Когда я ВСТАВЛЯЮ только одно или другое, я не получаю ошибку.
Вот этот spider.py
import scrapy
import MySQLdb
import MySQLdb.cursors
from scrapy.http.request import Request
from youtubephase2.items import Youtubephase2Item
class youtubephase2(scrapy.Spider):
name = 'youtubephase2'
def start_requests(self):
conn = MySQLdb.connect(user='uname', passwd='password', db='YouTubeScrape', host='localhost', charset="utf8", use_unicode=True)
cursor = conn.cursor()
cursor.execute('SELECT resultURL FROM SearchResults;')
rows = cursor.fetchall()
for row in rows:
if row:
yield Request(row[0], self.parse, meta=dict(start_url=row[0]))
cursor.close()
def parse(self, response):
for sel in response.xpath('//a[contains(@class, "yt-uix-servicelink")]'):
item = Youtubephase2Item()
item['newurl'] = sel.xpath('@href').extract()
item['start_url'] = response.meta['start_url']
yield item
Вот файл pipe.py, который показывает все три оператора self.cursor.execute.
import MySQLdb
import MySQLdb.cursors
import hashlib
from scrapy import log
from scrapy.exceptions import DropItem
from twisted.enterprise import adbapi
from youtubephase2.items import Youtubephase2Item
class MySQLStorePipeline(object):
def __init__(self):
self.conn = MySQLdb.connect(user='uname', passwd='password', db='YouTubeScrape', host='localhost', charset="utf8", use_unicode=True)
self.cursor = self.conn.cursor()
def process_item(self, item, spider):
try:
#self.cursor.execute("""UPDATE SearchResults SET NewURL = %s WHERE ResultURL = %s VALUES (%s, %s)""",(item['newurl'], item['start_url']))
#self.cursor.execute("""UPDATE SearchResults SET NewURL = %s WHERE ResultURL = %s""",(item['newurl'], item['start_url']))
self.cursor.execute("""INSERT INTO TestResults (NewURL, StartURL) VALUES (%s, %s)""",(item['newurl'], item['start_url']))
self.conn.commit()
except MySQLdb.Error, e:
log.msg("Error %d: %s" % (e.args[0], e.args[1]))
return item
Самый верхний оператор SQL SQL возвращает эту ошибку:
2017-04-13 18:29:34 [scrapy.core.scraper] ERROR: Error processing {'newurl': [u'http://www.tagband.co.uk/'],
'start_url': u'https://www.youtube.com/watch?v=UqguztfQPho'}
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/twisted/internet/defer.py", line 653, in _runCallbacks
current.result = callback(current.result, *args, **kw)
File "/root/scraping/youtubephase2/youtubephase2/pipelines.py", line 18, in process_item
self.cursor.execute("""UPDATE SearchResults SET AffiliateURL = %s WHERE ResultURL = %s VALUES (%s, %s)""",(item['affiliateurl'], item['start_url']))
File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 159, in execute
query = query % db.literal(args)
TypeError: not enough arguments for format string
Средний оператор выполнения SQL возвращает эту ошибку:
2017-04-13 18:33:18 [scrapy.log] INFO: Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') WHERE ResultURL = 'https://www.youtube.com/watch?v=UqguztfQPho'' at line 1
2017-04-13 18:33:18 [scrapy.core.scraper] DEBUG: Scraped from <200 https://www.youtube.com/watch?v=UqguztfQPho>
{'newurl': [u'http://www.tagband.co.uk/'],
'start_url': u'https://www.youtube.com/watch?v=UqguztfQPho'}
Последний оператор выполнения SQL возвращает ту же ошибку, что и середина, даже при использовании INSERT в новой базе данных. Кажется, чтобы добавить дополнительную одинарную цитату. Последний работает, когда я вставляю только один из элементов в базу данных.
2017-04-13 18:36:40 [scrapy.log] INFO: Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '), 'https://www.youtube.com/watch?v=UqguztfQPho')' at line 1
2017-04-13 18:36:40 [scrapy.core.scraper] DEBUG: Scraped from <200 https://www.youtube.com/watch?v=UqguztfQPho>
{'newurl': [u'http://www.tagband.co.uk/'],
'start_url': u'https://www.youtube.com/watch?v=UqguztfQPho'}
Извините за длинный пост. Пытаясь быть тщательным.
1 ответ
Я понял это. Проблема связана с тем, что я передавал список в конвейер выполнения MySQL.
Я создал конвейер, который преобразует список в строку с "".join(item['newurl']) и возвращает элемент до попадания в конвейер MySQL.
Возможно, есть лучший способ изменить строку item['newurl'] = sel.xpath('@href'). Extract() в spider.py, чтобы извлечь первый элемент в списке или преобразовать его в текст, но не Трубопровод работал на меня.