Использование Scrapy для очистки сайта, который использует XMLHttpRequests для загрузки его содержимого. - PullRequest
0 голосов
/ 17 апреля 2019

Сайт, который я пытаюсь очистить (в браузере), возвращает 50 должностей за раз.Когда я попытаюсь использовать скрап для возврата всех должностей, он будет очищать только 20 из них.

Ссылка на веб-страницу: https://recruiting.ultipro.com/COM1038/JobBoard/d22da326-8928-4fbc-8b3b-99b6db355d5d/?q=&o=postedDateDesc

Как только я зашел на эту страницу, я понял, что содержимое воспроизводится динамически, поэтому я щелкнул правой кнопкой мыши и осмотрел страницу и перезагрузил ее с помощью XHR>Вкладка «Сеть» открыта в Dev Tools.Он показывает два файла

  1. GetFilters
  2. LoadOpportunities

«LoadOpportunities», казалось многообещающим, поэтому я посмотрел «Ответ» на вкладке XHR ион возвратил то, что кажется файлом JSON, содержащим всю информацию, которую я когда-либо мог хотеть.Я использовал CTRL-f для поиска «Заголовок» и нашел 50 случаев.Отлично!

Итак, чтобы проверить это.Я открыл Scrapy Shell и просмотрел страницу, которая вернула JSON:

https://recruiting.ultipro.com/COM1038/JobBoard/d22da326-8928-4fbc-8b3b-99b6db355d5d/JobBoardView/LoadOpportunities

Когда вы открываете эту страницу в браузере, она возвращает только 20 из (текущих) 54вакансии.Я впервые обнаружил это, когда использовал пакет json и оболочку для очистки, чтобы очистить страницу.

Когда вы просматриваете вкладку «Предварительный просмотр» в браузере, используя первую ссылку, которую я разместил в файле «LoadOpportunities», вы видите, что она имеет до 50 значений под клавишей «возможности».я пытаюсь очистить значение 'Title' от каждого из них.

Я также создал скребок, который делает то же самое, используя ответ HTML, но он не особенно полезен. Он не выполняет свою работу, так как онфактически не взаимодействует с динамической веб-страницей, только частичный файл JSON, к которому подключена исходная страница.

import scrapy, re, json, requests
from ..items import MetroSouthItems

class MetroSouth(scrapy.Spider):
    name = "metrosouth"
    start_urls = [
    'https://recruiting.ultipro.com/COM1038/JobBoard/d22da326-8928-4fbc-8b3b-99b6db355d5d/JobBoardView/LoadOpportunities',
    ]

    def parse(self, response):
        html_res = response.body
        decoded_res = str(html_res,"utf-8")
        json_file = open("metrosouth.json", "w")
        json_file.write(decoded_res)
        with open("metrosouth.json") as json_data:
            data = json.load(json_data)
            items = MetroSouthItems()
            for i in range(len(data["opportunities"])):
                items["job_title"] = data["opportunities"][i]["Title"]
                print(i)
                yield items

Я хотел бы получить все доступные рабочие места, а затем в какой-то момент перенести их вВ базе данных / возможно, каждое утро нужно перезапускать паука, чтобы я мог отслеживать новые списки. Прямо сейчас я перезаписываю файл JSON новыми списками.

Если у кого-то есть какие-либо советы или рекомендации длядвигаясь вперед, я был бы очень признателен. У меня такое ощущение, что это как-то связано с Javascript, посколькускажем, что «LoadOpportunities» инициируется jslib, но у меня нет большого опыта работы с javascript и я не знаю, что все это значит.

1 Ответ

2 голосов
/ 17 апреля 2019

На странице изначально они делают POST-запрос с некоторой дополнительной полезной нагрузкой. Мы можем воспроизвести это примерно так:

import scrapy, json


class MetroSouth(scrapy.Spider):
    name = "metrosouth"
    search_url = url = 'https://recruiting.ultipro.com/COM1038/JobBoard/d22da326-8928-4fbc-8b3b-99b6db355d5d/JobBoardView/LoadOpportunities'

    def start_requests(self):
        payload = """{"opportunitySearch":{"Top":100,"Skip":0,"QueryString":"","OrderBy":[{"Value":"postedDateDesc","PropertyName":"PostedDate","Ascending":false}],"Filters":[{"t":"TermsSearchFilterDto","fieldName":4,"extra":null,"values":[]},{"t":"TermsSearchFilterDto","fieldName":5,"extra":null,"values":[]},{"t":"TermsSearchFilterDto","fieldName":6,"extra":null,"values":[]}]},"matchCriteria":{"PreferredJobs":[],"Educations":[],"LicenseAndCertifications":[],"Skills":[],"hasNoLicenses":false,"SkippedSkills":[]}}"""
        yield scrapy.Request(self.search_url, method='POST', body=payload)

    def parse(self, response):
        j = json.loads(response.text)
        print '======'
        for i, row in enumerate(j.get('opportunities')):
            print i, ' - ', row.get('Title')
        print '======'

Проверьте параметр Top в полезной нагрузке. Первоначально он установлен на 50, и запрос к странице дает нам 20 записей. Но я увеличил его до 100, и теперь я получаю все 54 записи. Надеюсь, это поможет.

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