Scrapy добавить данные в файл JSON из разных функций - PullRequest
0 голосов
/ 17 мая 2018

Я новичок в scrapy и json, и работаю над проектом scrapy. это мой сценарий:

import scrapy

class MoulaviSpider(scrapy.Spider):
    name = "moulavi"

    def start_requests(self):
    start_urls = [
        'https://ganjoor.net/moulavi/masnavi/daftar1/sh1/',
        'https://ganjoor.net/moulavi/masnavi/daftar1/sh2/',
    ]
        for url in start_urls:
            yield scrapy.Request(url=url, callback=self.title)

    def title(self, response):
        #'hetitle': response.css('h2').extract(), 
        return scrapy.Request(callback=self.parse)

    def parse(self, response):
        for line in response.css('div.b'):
            yield {
                'right_column': line.css('div.m1').extract(),
                'left_column': line.css('div.m2').extract(),
}

И я запускаю это с scrapy crawl moulavi -o moulavi.json.

Я знаю, что мой scrpit сейчас не верен. Я хочу добавить заголовок каждой страницы в файл json внутри "def title" , а затем вызвать "def parse" , чтобы добавить другие данные в файл json. Но так как я не очень хорошо знаком с callback или yield, поэтому не знаю, что делать.

Как вы можете видеть из моего кода, я прокомментировал строку, в которой я хочу добавить заголовок в файл json, но не знаю, как это сделать.

Итак, я хочу удалить URL, найти заголовок страницы и записать его в файл json, а после этого запустить цикл for, чтобы найти все теги div с классами 'm1' и ' m2 'и запишите их в файл json. А затем начните очищать следующий URL.

Я хочу, чтобы вывод был таким: (не suro, если синтаксис правильный)

{
"title":"first page title",
"content":[
    {"right_column": ["<div class=\"m1\"><p>من چگونه هوش دارم پیش و پس</p></div>"], "left_column": ["<div class=\"m2\"><p>چون نباشد نور یارم پیش و پس</p></div>"]},
    {"right_column": ["<div class=\"m1\"><p>عشق خواهد کین سخن بیرون بود</p></div>"], "left_column": ["<div class=\"m2\"><p>آینه غماز نبود چون بود</p></div>"]},
    {"right_column": ["<div class=\"m1\"><p>آینت دانی چرا غماز نیست</p></div>"], "left_column": ["<div class=\"m2\"><p>زانک زنگار از رخش ممتاز نیست</p></div>"]}
]
"title":"second page title",
"content":[
    {"right_column": ["<div class=\"m1\"><p>بشنو این نی چون شکایت می‌کند</p></div>"], "left_column": ["<div class=\"m2\"><p>از جداییها حکایت می‌کند</p></div>"]},
    {"right_column": ["<div class=\"m1\"><p>کز نیستان تا مرا ببریده‌اند</p></div>"], "left_column": ["<div class=\"m2\"><p>در نفیرم مرد و زن نالیده‌اند</p></div>"]},
]}

Заранее спасибо:)

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Обычно один метод отвечает за синтаксический анализ содержимого страницы, а затем дает проанализированные данные.В конце, после выдачи всех элементов, этот метод может дать больше запросов на последующие страницы, которые будут проанализированы, если это необходимо.

Анализируемые данные будут использоваться для создания экземпляра Item ,а затем затем передается через конвейер элементов для сложной обработки и сохранения.Здесь я придерживаюсь словарей, чтобы упростить пример.

Исходя из предоставленного вами вывода, content - это ключ верхнего уровня в выводе json, а его значение - список.Элемент списка представляет собой словарь с двумя ключами left_column & right_column, а значения имеют тип list.

В этом случае метод parse может выглядеть следующим образом:

import scrapy

class MoulaviSpider(scrapy.Spider):
    name = "moulavi"

    def start_requests(self):
        start_urls = [
            'https://ganjoor.net/moulavi/masnavi/daftar1/sh1/',
            'https://ganjoor.net/moulavi/masnavi/daftar1/sh2/',
        ]

        for url in start_urls:
            yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response):
        # build up the content through a list comprehension
        # consider using `extract_first` instead of `extract` for 
        # less nested output
        content = [
          {'right_column': line.css('div.m1').extract(),
           'left_column': line.css('div.m2').extract()}
          for line in response.css('div.b')
        ]            
        yield {'title': response.css('h2').extract_first(),
               'content': content}

Обратите внимание, что для извлечения title я использовал extract_first вместо извлечения.Также рассмотрите возможность использования extract_first для значений left_column & right_column, так как они кажутся списками из 1 элемента.

0 голосов
/ 17 мая 2018

Вам не нужно создавать новый обратный вызов только для анализа заголовка, вы можете создать структуру, которую вы хотите, внутри функции parse, вам нужно просто создать объект со свойствами, которые вы хотите.

# -*- coding: utf-8 -*-
import scrapy

class MoulaviSpider(scrapy.Spider):
    name = 'moulavi'

    def start_requests(self):

        start_urls = [
            'https://ganjoor.net/moulavi/masnavi/daftar1/sh1/',
            'https://ganjoor.net/moulavi/masnavi/daftar1/sh2/',
        ]

        for url in start_urls:
            yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response):

        item = dict(title=response.xpath('//title/text()').extract_first(),content=[])

        for line in response.css('div.b'):
            item['content'].append({
                'right_column': line.css('div.m1').extract_first(),
                'left_column': line.css('div.m2').extract_first()})

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