Python Requests: Как извлекать данные с пагинацией более 1000 записей из Верховного суда NJDG?

Вопрос или проблема

Я пытаюсь собрать все доступные данные для каждого “типа утилизации” с сайта Национальной судебной сетки данных (NJDG) (раздел Верховного суда) – ссылка на сайт. Таблица отображает до 1000 записей на странице и имеет кнопку “Далее”, чтобы загрузить следующий набор из 1000 записей.

Проблема: Мой текущий код на Python извлекает только первые 1000 записей, но не получает дополнительные страницы, хотя в таблице есть больше записей. Например, для категории “Разрешено” доступно 2400 записей, а мой код возвращает только первые 1000.

Мне нужна помощь с:

Корректировкой моего кода для правильной обработки пагинации (т.е. имитируя нажатие кнопки “Далее”). Извлечением всех доступных записей для каждого типа утилизации, а не только первых 1000 записей.

Скриншот:
Вот скриншот таблицы для справки: введите описание изображения здесьвведите описание изображения здесь

import requests
import json

# Определяем базовый URL для POST-запроса
url = "https://njdg.ecourts.gov.in/scnjdg/?p=home/casewiseList"

# Определяем заголовки (одинаковы для всех запросов)
headers = {
    'Accept': 'application/json, text/javascript, */*; q=0.01',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
    'X-Requested-With': 'XMLHttpRequest',
    'Cookie': 'YOUR_COOKIE_DATA_HERE',  # Замените на полный куки из вашего захвата
}

# Список со всеми типами утилизации и соответствующими токенами приложения
disposed_types = [
    {'val': 'Разрешено', 'app_token': '2b0e6e5055adb7c128398139170dca6e6b72e07f98c8d3f0f009d96831132a47'},
    {'val': 'Условный приказ', 'app_token': '82008d8eeeabbcf84afc073d52511177d2a7a5027b4e3d84dd5b635d4f0b3b0f'},
    {'val': 'Отклонено', 'app_token': '7822e5682b3fe4c4e9f41fbbb16c559f5f29b12e32712e67530dbc910d490a54'},
    {'val': 'Утилизировано', 'app_token': '1e286253c751422f9ad0ae4af7913cffc8c8e00b35664a5fd32056eea9387ce4'},
    {'val': 'Предоставлено', 'app_token': '57d35c7e14334c7fdff87bbc9cf46a385ea79e9e3a80b778cbc43614e466f22a'},
    {'val': 'Другие', 'app_token': 'b30e998579ac60d3c517fb7291257138c0575a2660fbd4a5bd6fb6fe24d58385'}
]

# Определяем общий шаблон postData
post_data_template = (
    'sEcho={sEcho}&iColumns=4&sColumns=,,,&iDisplayStart={iDisplayStart}&iDisplayLength={iDisplayLength}'
    '&mDataProp_0=0&sSearch_0=&bRegex_0=false&bSearchable_0=true&bSortable_0=true'
    '&mDataProp_1=1&sSearch_1=&bRegex_1=false&bSearchable_1=true&bSortable_1=true'
    '&mDataProp_2=2&sSearch_2=&bRegex_2=false&bSearchable_2=true&bSortable_2=true'
    '&mDataProp_3=3&sSearch_3=&bRegex_3=false&bSearchable_3=true&bSortable_3=true'
    '&sSearch=&bRegex=false&iSortCol_0=0&sSortDir_0=asc&iSortingCols=1'
    '&flag=natDisp&state_code=&dist_code=&ci_cri=2&val={val}&active_tab=disposed'
    '&casetypeval=&monthInsDisp=undefined&disp_year=2019&search_by=&dashFlag=reg&ajax_req=true'
    '&app_token={app_token}'
)

# Функция для извлечения данных для конкретного типа утилизации
def fetch_data(start, length, sEcho, val, app_token):
    post_data = post_data_template.format(
        sEcho=sEcho,
        iDisplayStart=start,
        iDisplayLength=length,
        val=val,
        app_token=app_token
    )
    response = requests.post(url, headers=headers, data=post_data)
    return response.json()  # Предполагается, что ответ в формате JSON

# Функция для перебора всех типов утилизации и извлечения всех страниц
def fetch_all_disposed_data(disposed_types):
    all_data = {}
    for disposed_type in disposed_types:
        val = disposed_type['val']
        app_token = disposed_type['app_token']
        sEcho = 1  # Увеличиваем это значение для каждого запроса
        start = 0  # Начальный индекс (пагинация)
        length = 1000  # Количество записей на запрос

        # Первый запрос для получения общего количества записей
        initial_data = fetch_data(start=start, length=length, sEcho=sEcho, val=val, app_token=app_token)
        total_records = initial_data.get("iTotalRecords", 0)
        print(f"Извлечение {total_records} записей для типа утилизации {val}...")

        disposed_data = [initial_data]

        # Цикл по всем страницам для извлечения данных, пока все записи не будут получены
        while start + length < total_records:
            start += length  # Переход к следующей странице
            sEcho += 1  # Увеличиваем sEcho для следующего запроса
            data = fetch_data(start=start, length=length, sEcho=sEcho, val=val, app_token=app_token)
            disposed_data.append(data)

        # Извлечение оставшихся записей
        if start < total_records:
            sEcho += 1
            data = fetch_data(start=start, length=total_records - start, sEcho=sEcho, val=val, app_token=app_token)
            disposed_data.append(data)

        # Сохранение данных для каждого типа утилизации
        all_data[val] = disposed_data

    return all_data

# Извлекаем и сохраняем данные для всех типов утилизации
disposed_data = fetch_all_disposed_data(disposed_types)

# Сохраняем данные в JSON файл для дальнейшей обработки
with open("disposed_data_2019.json", "w") as f:
    json.dump(disposed_data, f, indent=4)

print("Сбор данных завершен и сохранен в disposed_data_2019.json")

Ожидаемое поведение:
Я ожидаю, что код извлечет все записи для каждого типа утилизации (например, 2400 записей для "Разрешено") на нескольких страницах.
Каждый запрос должен извлекать следующий набор данных, пока не будут получены все записи.
Текущий вывод:
Скрипт извлекает только первые 1000 записей и не переходит к следующему набору записей.

Что я пробовал:
Я увеличиваю iDisplayStart на 1000 для каждого запроса, чтобы смоделировать пагинацию.
Я проверяю iTotalRecords, чтобы узнать, сколько записей существует для каждого типа утилизации.
Что мне нужно:
Как мне правильно пройти через все доступные записи и убедиться, что я собираю весь набор данных для каждого типа утилизации?

Любая помощь или предложения будут приветствоваться!

Ответ или решение

Чтобы успешно извлечь все данные по каждому типу утилизации с сайта Национальной судебной базы данных (NJDG) для Верховного суда, необходимо внести некоторые изменения в ваш код, чтобы корректно обрабатывать пагинацию. Давайте рассмотрим, как можно улучшить вашу реализацию.

Общая структура решения:

  1. Отправка POST-запросов для получения данных: Мы будем отправлять POST-запрос с параметрами для получения данных.
  2. Обработка пагинации: Будем использовать правильные параметры, чтобы переходить на следующие страницы, пока не будут получены все записи.
  3. Сохранение данных: Полученные данные будут сохранены в формате JSON.

Изменённый код

Вот переписанный код с учётом вышеперечисленных моментов:

import requests
import json

# URL для POST-запроса
url = "https://njdg.ecourts.gov.in/scnjdg/?p=home/casewiseList"

# Заголовки для запросов
headers = {
    'Accept': 'application/json, text/javascript, */*; q=0.01',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'User-Agent': 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
    'X-Requested-With': 'XMLHttpRequest',
    'Cookie': 'YOUR_COOKIE_DATA_HERE',  # Замените на актуальные данные cookie
}

# Типы утилизации и токены приложения
disposed_types = [
    {'val': 'Allowed', 'app_token': '2b0e6e5055adb7c128398139170dca6e6b72e07f98c8d3f0f009d96831132a47'},
    {'val': 'Conditional Order', 'app_token': '82008d8eeeabbcf84afc073d52511177d2a7a5027b4e3d84dd5b635d4f0b3b0f'},
    {'val': 'Dismissed', 'app_token': '7822e5682b3fe4c4e9f41fbbb16c559f5f29b12e32712e67530dbc910d490a54'},
    {'val': 'Disposed of', 'app_token': '1e286253c751422f9ad0ae4af7913cffc8c8e00b35664a5fd32056eea9387ce4'},
    {'val': 'Granted', 'app_token': '57d35c7e14334c7fdff87bbc9cf46a385ea79e9e3a80b778cbc43614e466f22a'},
    {'val': 'Others', 'app_token': 'b30e998579ac60d3c517fb7291257138c0575a2660fbd4a5bd6fb6fe24d58385'}
]

post_data_template = (
    'sEcho={sEcho}&amp;iColumns=4&amp;sColumns=,,,&amp;iDisplayStart={iDisplayStart}&amp;iDisplayLength={iDisplayLength}'
    '&amp;mDataProp_0=0&amp;sSearch_0=&amp;bRegex_0=false&amp;bSearchable_0=true&amp;bSortable_0=true'
    '&amp;mDataProp_1=1&amp;sSearch_1=&amp;bRegex_1=false&amp;bSearchable_1=true&amp;bSortable_1=true'
    '&amp;mDataProp_2=2&amp;sSearch_2=&amp;bRegex_2=false&amp;bSearchable_2=true&amp;bSortable_2=true'
    '&amp;mDataProp_3=3&amp;sSearch_3=&amp;bRegex_3=false&amp;bSearchable_3=true&amp;bSortable_3=true'
    '&amp;sSearch=&amp;bRegex=false&amp;iSortCol_0=0&amp;sSortDir_0=asc&amp;iSortingCols=1'
    '&amp;flag=natDisp&amp;state_code=&amp;dist_code=&amp;ci_cri=2&amp;val={val}&amp;active_tab=disposed'
    '&amp;casetypeval=&amp;monthInsDisp=undefined&amp;disp_year=2019&amp;search_by=&amp;dashFlag=reg&amp;ajax_req=true'
    '&amp;app_token={app_token}'
)

def fetch_data(start, length, sEcho, val, app_token):
    post_data = post_data_template.format(
        sEcho=sEcho,
        iDisplayStart=start,
        iDisplayLength=length,
        val=val,
        app_token=app_token
    )
    response = requests.post(url, headers=headers, data=post_data)
    return response.json()

def fetch_all_disposed_data(disposed_types):
    all_data = {}
    for disposed_type in disposed_types:
        val = disposed_type['val']
        app_token = disposed_type['app_token']
        sEcho = 1
        start = 0
        length = 1000

        # Получение общего количества записей
        initial_data = fetch_data(start, length, sEcho, val, app_token)
        total_records = initial_data.get("iTotalRecords", 0)
        print(f"Ищем {total_records} записей для типа утилизации {val}...")

        disposed_data = initial_data['aaData']

        # Пагинация
        while start + length < total_records:
            start += length
            sEcho += 1
            data = fetch_data(start, length, sEcho, val, app_token)
            disposed_data.extend(data['aaData'])  # Объединяем данные с предшествующими

        # Сохраняем данные для каждого типа утилизации
        all_data[val] = disposed_data

    return all_data

# Получение и сохранение данных
disposed_data = fetch_all_disposed_data(disposed_types)

with open("disposed_data_2019.json", "w") as f:
    json.dump(disposed_data, f, indent=4)

print("Получение данных завершено, данные сохранены в disposed_data_2019.json")

Объяснение изменений:

  1. Решение проблемы пагинации: Мы продолжаем запрашивать данные с обновлённым start и sEcho, пока не получим все записи.
  2. Сбор данных: Ответы объединяются в единую коллекцию disposed_data, что позволяет получать все результаты для каждого типа утилизации.
  3. Исправлены операции: Добавлены проверки на количество записей, чтобы избегать избыточных запросов.

Заключение

С этими изменениями ваш код должен корректно обрабатывать пагинацию и извлекать все доступные данные по каждому типу утилизации с NJDG. Убедитесь, что ваши заголовки и cookie актуальны для успешного выполнения запросов.

Оцените материал
Добавить комментарий

Капча загружается...