Scrapy Pipeline для обновления mysql для каждого start_url

У меня есть паук, который читает start_urls из базы данных MySQL и удаляет неизвестное количество ссылок с каждой страницы. Я хочу использовать pipelines.py для обновления базы данных с помощью очищенных ссылок, но я не знаю, как вернуть start_url обратно в конвейер для оператора SQL UPDATE.

Вот код паука, который работает.

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)
    cursor.close()

def parse(self, response):
    for sel in response.xpath('//a[contains(@class, "yt-uix-servicelink")]'):
        item = Youtubephase2Item()
        item['pageurl'] = sel.xpath('@href').extract()
        yield item

А вот файл pipe.py, в котором я хочу обновить базу данных, используя ссылки, очищенные с использованием start_url в качестве критерия WHERE для оператора SQL UPDATE. Таким образом, start_url в операторе SQL является заполнителем того, что я хотел бы достичь.

import MySQLdb
import MySQLdb.cursors
import hashlib
import re
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 PageURL = %s WHERE ResultURL = start_url[
                    VALUES (%s)""",
                   (item['pageurl']
                                    ))

        self.conn.commit()

    except MySQLdb.Error, e:
        log.msg("Error %d: %s" % (e.args[0], e.args[1]))

    return item

Надеюсь, мой вопрос достаточно ясен. В прошлом я успешно использовал pipe.py для вставки элементов в базу данных.

1 ответ

Решение

Вы можете использовать meta Параметр запроса для передачи соответствующей информации между связанными запросами и элементами:

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['pageurl'] = sel.xpath('@href').extract()
        item['start_url'] = response.meta['start_url']
        yield item

Теперь вы также можете использовать response.url, но это может измениться из-за перенаправлений или других вещей, так что это может позже отличаться от того, что у вас есть в вашей базе данных.

Наконец, вы должны обновить свой конвейер, чтобы также передать item['start_url'] как start_url параметр в вашем cursor.execute

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