Не отображаются ключи в json

Подскажите пожалуйста, где я мог ошибиться при запросе json, что у меня не отображаются ключи working_days, working_time_intervals, working_time_modes, experience, emploement, accept_temporary Вот сам код .ipynb:

import requests      # Для запросов по API
import json          # Для обработки полученных результатов
import time          # Для задержки между запросами
import os            # Для работы с файлами
import pandas as pd  # Для формирования датафрейма с результатами

def getAreas():
    req = requests.get('https://api.hh.ru/areas')    
    data = req.content.decode()
    req.close()
    jsObj = json.loads(data)
    areas = []
    for k in jsObj:
        for i in range(len(k['areas'])):
            if len(k['areas'][i]['areas']) != 0:  # Если у зоны есть внутренние зоны
                for j in range(len(k['areas'][i]['areas'])):
                    areas.append([k['id'], 
                                  k['name'], 
                                  k['areas'][i]['areas'][j]['id'],
                                  k['areas'][i]['areas'][j]['name']])
            else:  # Если у зоны нет внутренних зон
                areas.append([k['id'], 
                              k['name'], 
                              k['areas'][i]['id'], 
                              k['areas'][i]['name']])
    return areas

areas = getAreas()

def getEmployers():
    req = requests.get('https://api.hh.ru/employers')
    data = req.content.decode()
    req.close()
    count_of_employers = json.loads(data)['found']
    employers = []
    i = 0
    j = count_of_employers
    while i < j:
            req = requests.get('https://api.hh.ru/employers/'+str(i+1))
            data = req.content.decode()
            req.close()
            jsObj = json.loads(data)
            try:
                employers.append([jsObj['id'], jsObj['name']])
                i += 1
                print([jsObj['id'], jsObj['name']])
            except:
                i += 1
                j += 1
            if i % 200 == 0:
                time.sleep(0.01)
    return employers
    
employers = getEmployers()

def getPage(page, area):
    params = {
              'employer_id': 3529,  # ID 2ГИС
              'area': area,         # Поиск в зоне
              'page': page,         # Номер страницы
              'per_page': 100       # Кол-во вакансий на 1 странице
             }   
    req = requests.get('https://api.hh.ru/vacancies', params)
    data = req.content.decode() 
    req.close()
    return data

for area in areas:
    for page in range(0, 20):
        jsObj = json.loads(getPage(page, area[2]))
        if not os.path.exists('./areas/'):
            os.makedirs('./areas/')
        nextFileName = './areas/{}.json'.format(str(area[2])+'_'+str(area[3])+'_'+str(page))
        f = open(nextFileName, mode='w', encoding='utf8')
        f.write(json.dumps(jsObj, ensure_ascii=False))
        f.close()
        if (jsObj['pages'] - page) <= 1:  
            print('[{0}/{1}] Область: {3} ({2}) - {5} ({4}) Вакансий: {6}'.\
                  format(area_list_id+1, len(areas), area[0], area[1], area[2], area[3], jsObj['found']))
            break
    time.sleep(0.2)

dt = []
for fl in os.listdir('./areas/'):
    f = open('./areas/{}'.format(fl), encoding='utf8')
    jsonText = f.read()
    f.close()
    jsonObj = json.loads(jsonText)
    if jsonObj['found'] != 0:
        for js in jsonObj['items']:
            if js['salary'] != None:
                salary_from = js['salary']['from']
                salaty_to = js['salary']['to']
            else:
                salary_from = None
                salaty_to = None
            if js['address'] != None:
                address_raw = js['address']['raw']
            else:
                address_raw = None
            dt.append([
                js['id'],
                js['premium'],
                js['name'],
                js['department']['name'],
                js['has_test'],
                js['response_letter_required'],
                js['area']['id'],
                js['area']['name'],
                salary_from, 
                salaty_to,
                js['type']['name'],
                address_raw,
                js['response_url'],
                js['sort_point_distance'],
                js['published_at'],
                js['created_at'],
                js['archived'],
                js['apply_alternate_url'],
                js['insider_interview'],
                js['url'],
                js['alternate_url'],
                js['relations'],
                js['employer']['id'],
                js['employer']['name'],
                js['snippet']['requirement'],
                js['snippet']['responsibility'],
                js['contacts'],
                js['schedule']['name'],
                js['working_days'],
                js['working_time_intervals'],
                js['working_time_modes'],
                js['accept_temporary']
                ])

df = pd.DataFrame(dt, columns = [
                                'id',
                                'premium',
                                'name',
                                'department_name',
                                'has_test',
                                'response_letter_required',
                                'area_id',
                                'area_name',
                                'salary_from', 
                                'salaty_to',
                                'type_name',
                                'address_raw',
                                'response_url',
                                'sort_point_distance',
                                'published_at',
                                'created_at',
                                'archived',
                                'apply_alternate_url',
                                'insider_interview',
                                'url',
                                'alternate_url',
                                'relations',
                                'employer_id',
                                'employer_name',
                                'snippet_requirement',
                                'snippet_responsibility',
                                'contacts',
                                'schedule_name',
                                'working_days',
                                'working_time_intervals',
                                'working_time_modes',
                                'accept_temporary'
                                ])   
df.to_excel('result_2gis.xlsx')

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


Ответы (1 шт):

Автор решения: Namerek

Ни в коем случае не претендую на ответ (ответил в комментарии).

Из-за непонимания конечной цели, решение, даже близко, не идеальное. Просто захотелось сделать пару набросков для топикстартера. Старался придерживаться той структуры которую он создает.

Итак...

pip install fake-useragent tqdm requests requests-toolbelt jmespath

from fake_useragent import UserAgent
from requests.adapters import HTTPAdapter
from requests_toolbelt.sessions import BaseUrlSession
from tqdm import tqdm
from urllib3 import Retry
from multiprocessing.pool import ThreadPool as Pool

u_agent = UserAgent()

s = BaseUrlSession('https://api.hh.ru')
s.mount(
    'https://',
    HTTPAdapter(
        max_retries=Retry(
            status_forcelist=[502],
            backoff_factor=.0005,
            connect=3,
            read=2,
            other=5,
            total=5,
            raise_on_status=False
        ),
        pool_connections=10,
        pool_maxsize=5
    )
)
s.headers.update(
    {
        'User-Agent': u_agent.firefox
    }
)

import jmespath as js

response = s.get('areas')
data = response.json()
countries = dict(js.search('[*].[id,name]', data))
regions = dict(js.search('[*].areas[*].[id,name][]', data))
districtions = dict(js.search('[*].areas[*].areas[*].[id,name][][]', data))


employers = []
bar = tqdm(total=len(countries.items()))


def get_portals_employers(portal: str):
    pp = 0
    data_part = []
    while (pr := s.get(
            'employers/',
            params={
                'per_page': 100,
                'host': portal,
                'page': pp,
                'only_with_vacancies': True,
                # 'employer_type': 'company',
                'area': code
            }
    )).ok:
        pj = pr.json()
        data_part.extend(pj['items'])
        pp += 1
    return data_part


for code, name in countries.items():
    bar.desc = name
    bar.refresh()

    with Pool(7) as pool:
        # noinspection SpellCheckingInspection
        for elem in pool.imap_unordered(get_portals_employers, [
            'hh.ru',
            'rabota.by',
            'hh1.az',
            'hh.uz',
            'hh.kz',
            'headhunter.ge',
            'headhunter.kg',
        ]):
            employers += elem
    bar.update()
bar.desc = 'Complete'
bar.refresh()
bar.close()

Complete: 100%|██████████| 9/9 [02:23<00:00, 15.95s/it]      


vacancies = []


def get_vacations(empl: dict):
    if (v_response := s.get(
            empl['vacancies_url'],
    )).ok:
        return v_response.json()['items']
    return []


with Pool(20) as pool:
    for item in tqdm(pool.imap_unordered(get_vacations, employers), total=len(employers)):
        vacancies += item

  2%|▏         | 1959/128312 [00:39<42:35, 49.44it/s] 

только думаю, что когда этот цикл отработает (а скорее всего в процессе) ваш IP окажется в бане на HH.ru на какое-то время.

→ Ссылка