Есть ли что-нибудь вроде # spliter в scrapy?

#python #web-scraping #scrapy

#python #очистка веб-страниц #scrapy

Вопрос:

Я очищаю https://www.patelco.org/search-results#stq=amp;stp=1 , я хочу очистить все страницы, у меня есть общее представление о scrapy, вот код, который я использую:

 import scrapy
import json

class PatelcospiderSpider(scrapy.Spider):
    name = 'patelcospider'
    start_urls = ['https://www.patelco.org/search-results''#stq=amp;stp=1']
    def parse(self, response):
        columns = {
            "question": [],
            "answer": []
        }
        QUESTION_ANSWER_SELECTOR = ".st-ui-result"
        QUESTION_SELECTOR = ".st-ui-type-heading ::text"
        ANSWER_SELECTOR = ".st-ui-type-detail ::text"
        questions_answers = response.css(QUESTION_ANSWER_SELECTOR)
        for question_answer in questions_answers:
            question = question_answer.css(QUESTION_SELECTOR).getall()
            question = " ".join(question).strip()
            answer = question_answer.css(ANSWER_SELECTOR).getall()
            answer = " ".join(answer).strip()
            columns["question"].append(question)
            columns["answer"].append(answer)
            columns["link"].append(response.url)
        return columns
  

При выполнении он не возвращает никакого значения. Вот соответствующий вывод:

2020-08-28 20:39:48 [scrapy.core.engine] ИНФОРМАЦИЯ: Открыт Spider

2020-08-28 20:39:48 [scrapy.extensions.logstats] ИНФОРМАЦИЯ: просмотрено 0 страниц (со скоростью 0 страниц / мин), очищено 0 элементов (со скоростью 0 элементов / мин)

2020-08-28 20:39:48 [scrapy.extensions.telnet] ИНФОРМАЦИЯ: Консоль Telnet прослушивает 127.0.0.1:6023

2020-08-28 20:39:55 [scrapy.core.engine] ОТЛАДКА: обход (200) <ПОЛУЧИТЬ <диапазон>https://www.patelco.org/search-results#stq=amp;stp=1 >» rel=»nofollow noreferrer»> (ссылка: отсутствует)

2020-08-28 20:39:56 [scrapy.core.scraper] ОТЛАДКА: очищено от <200» rel=»nofollow noreferrer»>https://www.patelco.org/search-results >

{‘вопрос’: [], ‘ответ’: []}

2020-08-28 20:39:56 [scrapy.core.engine] ИНФОРМАЦИЯ: Закрытие spider (завершено)

Я думаю, проблема в том, что Scrapy ползетhttps://www.patelco.org/search-results которому на самом деле нечего возвращать. Я провел много поисков, но я не знаю, как это решить.

Заранее спасибо.

Ответ №1:

Это потому, что страница загружается с помощью javascript. Вы можете проверить это самостоятельно в Chrome dev tools.

Проверьте страницу -> Три точки в правой части панели -> Дополнительные инструменты -> настройки -> Отладчик -> Отключить javascript.

Есть два метода, которые вы можете использовать для очистки динамического содержимого. Под динамическим контентом я подразумеваю, что javascript использует HTTP-запросы для сбора данных и отображения их на веб-странице. Многие современные сайты отображают информацию таким образом. Это создает проблему при очистке.

  1. Реинжиниринг HTTP-запросов
  2. Использование автоматизации браузера

Первое — это всегда первый выбор, посмотрите, есть ли у веб-сайта конечная точка API, которую вы можете использовать. Это быстро, эффективно и масштабируемо. В отличие от автоматизации браузера, это последнее средство или если функциональность слишком сложна и нет доступного API. Это медленно, хрупко для изменений в HTML веб-сайта и не очень масштабируемо.

К счастью для вас, для этого есть конечная точка API. Откуда я могу это знать? Снова используя chrome dev tools.

Проверьте страницу -> Сетевые инструменты -> XHR

XHR означает HTTP-запрос XML, все, что связано с сервером, который всегда выполняют API, запросы отправляются в эту часть инструментов разработки.

Вы можете увидеть ‘search.json’

введите описание изображения здесь

Мы можем скопировать этот запрос на веб-сайт, который преобразует команды cURL в python (curl.trillworks.com )

введите описание изображения здесь

Это код, который преобразует веб-сайт. Это обеспечивает полезный способ преобразования запроса в словари Python и т.д…

 import requests


data = {
  'q': '',
  'page': '1'
}

response = requests.post('https://search-api.swiftype.com/api/v1/public/installs/Ty14DuZryzPDG_wzbyzh/search.json', data=data)
response.json()
  

Теперь, если вы скопируете запрос, вы также получите заголовки, и с запросом стоит поиграть. Для некоторых запросов требуется простой HTTP get-запрос без каких-либо заголовков, данных, параметров, файлов cookie. Другим потребуется намного больше. Здесь все, что нам нужно сделать, это указать номер страницы в параметре data.

Вывод

 {'record_count': 10,
 'records': {'page': [{'url': 'https://www.patelco.org/',
    'sections': ['You can count on us',
     'Better rates, more savings and all about YOU.',
     'Our community',
     'Join us',
     'What are your dreams and goals?',
     'Lower my debt',
     'Build my savings',
     'Purchase a home',
     'Plan for the future',
     'Manage my retirement',
     "Who we've helped",
     'UPGRADE MY HOME',
     'SUPERIOR SERVICE',
     'APPLY FOR A LOAN'],
    'title': 'Serving San Francisco Bay Area, Santa Rosa amp; Sacramento - Patelco Credit Union', ..... 
  

Там много информации, но мы можем использовать это, чтобы сделать простой запрос scrapy, чтобы сделать то же самое.

Пример кода для Scrapy

 def start_urls(self):
    url = 'https://search-api.swiftype.com/api/v1/public/installs/Ty14DuZryzPDG_wzbyzh/search.json'
    data = {
      'q': '',
      'page': '1'
    }
    yield scrapy.Request(url=url, meta={'data':data}, callback=self.parse)
def parse(self,response):
    response.json()
  

Обратите внимание, что meta аргумент — это способ убедиться, что запрос также содержит данные, которые мы хотим отправить по HTTP-запросу. Без этого вы не получите правильный объект JSON, который вы хотите.

Здесь response.json() будет преобразован объект JSON в словарь python. Я обычно играю с пакетом запросов, чтобы подумать о данных, которые я хочу отобразить перед кодированием в scrapy, из-за вложенности, которую вы получаете в отображаемом словаре.

В качестве примера этого

 response.json()['records']['page'][0]['title']
  

Соответствует результату

 'Serving San Francisco Bay Area, Santa Rosa amp; Sacramento - Patelco Credit Union'
  

При преобразовании объектов JSON в словари часто возникает много вложенности, поэтому я использую пакет запросов, чтобы сначала разобраться с этим. Страницы вложены за response.json()['records']['page']

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

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

Комментарии:

1. Большое вам спасибо, это буквально объясняет все, что у меня было в голове. Я выяснил, что search.json на вкладке network I, но не смог его извлечь. У меня было смутное представление об API, и я действительно боролся за последний месяц. И об извлечении большего количества страниц, которые я зациклил на странице no. и это работает. Еще раз спасибо.