Как сопоставить ПУНКТ с записью в базе данных? - PullRequest
1 голос
/ 23 декабря 2019

Я храню URL-адреса в таблице базы данных:

 scrapy_id  | scrapy_name   |    url    
------------+---------------+-----------------
        111 |       aaa     |  http://url1.com   
        222 |       bbb     |  http://url2.com 
        333 |       ccc     |  http://url3.com   

Мне нужен стартовый запрос из URL, поэтому я инициализирую соединение с базой данных в open_spider конвейера:

class PgsqlPipeline(object):

...

    def open_spider(self, spider):
        self.conn = psycopg2.connect(database=self.XXX, user=self.XXX, password=self.XXX)
        self.cur = self.conn.cursor()
        spider.myPipeline = self

    def get_urls(self):
        get_urls_sql = """
        SOME_SQL_STATMENTS
        """

        self.cur.execute(get_urls_sql)
        rows = self.cur.fetchall()
        return rows

...

, затем, в пауке:

....

class SephoraSpider(Spider):
    name = 'XXX'
    allowed_domains = ['XXX']

    def start_requests(self):
        for row in self.myPipeline.get_urls():
            self.item = SomeItem()
            url = str(row[2])
            self.item['id'] = row[0]
            self.item['name'] = row[1]
            yield Request(self.url, callback=self.parse_item)

    def parse_item(self, response):
        self.item['text'] = response.xpath('XXXX').get()
        return self.item

....

в предметах:

....

class SomeItem(Item):
    id = Field()
    name = Field()
    text = Field()
....

Я хочу получить следующий предмет:

{
    "id": 111,
    "name": "aaa",
    "text": response1,
},
{
    "id": 222,
    "name": "bbb",
    "text": response2,
},
{
    "id": 333,
    "name": "ccc",
    "text": response3,
}

Но я получаю:

{
    "id": 333,
    "name": "ccc",
    "text": response1,
},
{
    "id": 333,
    "name": "ccc",
    "text": response2,
},
{
    "id": 333,
    "name": "ccc",
    "text": response3,
}

Проблема может заключаться в том, что я помещаю self.item = SomeItem() в start_requests (), но если я поставлю self.item = SomeItem() в parse_item (), я не могу получить id и name, это означает, что не может сопоставить разрешенный ответ с его идентификатором.

Как сопоставить ПУНКТ с записью в базе данных?

1 Ответ

1 голос
/ 23 декабря 2019

Вы не можете использовать self для хранения метаданных запроса, потому что вы устанавливаете его только при запуске запросов;вам нужно, чтобы данные сохранялись вместе с запросом, а не с экземпляром класса SephoraSpider. В обратном вызове parse_item для него будет установлено значение последнего запущенного вами запроса. Вместо этого вы можете использовать поле Request.meta:

class SephoraSpider(Spider):
    name = 'XXX'
    allowed_domains = ['XXX']

    def start_requests(self):
        for row in self.myPipeline.get_urls():
            url = str(row[2])
            item = {'id': row[0], 'name': row[1], 'url': row[2]}
            yield Request(self.url, callback=self.parse_item, meta={'item': item})

    def parse_item(self, response):
        item = response.meta['item']
        item['text'] = response.xpath('XXXX').get()
        return item

Подробности в документах .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...