цикл while true в python

Вопрос по завершению цикла while при парсинге

offset = 1

while True:
    website = f'https://new.zonafilm.ru/api/series?page={offset}'
    usag = fake_useragent.UserAgent().random
    random_usag = {"User-Agent": usag}
    respon = requests.get(website, headers=random_usag).json()
    data = respon.get('data')
    files = []
    for item in data:
        if 'description' in item :
            files.append({
                'title': item.get('title'),
                'desc': item.get('description'),
                'image': item.get('cover_url')

            })
        else:
            break

    print(files)
    offset += 1

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

Прошу пнуть в нужном направлении, где допустил ошибку, к сожалению, сам не могу дойти до решения.
Заранее спасибо, и извиняюсь за, возможно, глупый вопрос.


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

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

Так у тебя вообще выхода из цикла в коде нет.

if not data: break
→ Ссылка
Автор решения: AnnaBazueva

Walrus

Моржовый (walrus) оператор, появившийся в Python 3.8,
дает возможность решить сразу две задачи:

  1. присвоить значение переменной
  2. вернуть это значение


Первое, files = [] должен быть вне цикла while.

Второе, напиши функцию get_data(offset), в ней это всё: website, usag, random_usag
и вызывай её в условии цикла:

def get_data(offset):
    if offset < 11:
        return f"offset == {offset}"
    else:
        return None

offset = 1

while data := get_data(offset):
    # далее обработка...
    print(data)
    offset += 1


Для оператора ”walrus” есть PEP 572,
начните знакомство с раздела Примеры (Examples)

→ Ссылка
Автор решения: Qwertiy

Раз уж некоторые хотят архитектурно красивое решение, то, по-моему, надо делать так (не смог проверить, надеюсь, работает):

def get_data():
  offset = 1

  while True:
    website = f'https://new.zonafilm.ru/api/series?page={offset}'
    usag = fake_useragent.UserAgent().random
    random_usag = {"User-Agent": usag}
    respon = requests.get(website, headers=random_usag).json()
    data = respon.get('data')

    if data:
      yield from data
    else:
      break

    offset += 1

files = [{
  'title': item.get('title'),
  'desc': item.get('description'),
  'image': item.get('cover_url')
} for item in get_data()]

print(files)

Поведение здесь отличается от того, что в вопросе, поскольку там через print выводилась каждая страница в отдельности, а тут - только все данные вместе.


Если нужно изменить так, чтобы вывод появлялся по мере появления данных, надо сделать вывод по одной строке с помощью

for item in get_data():
  print({
    'title': item.get('title'),
    'desc': item.get('description'),
    'image': item.get('cover_url')
  })

Если важны именно страницы, то надо выкинуть отсюда from

yield from data

После чего в цикле for обрабатывать страницы:

for items in get_data():
  files = [{
    'title': item.get('title'),
    'desc': item.get('description'),
    'image': item.get('cover_url')
  } for item in items]

  print(files)

PS: В зависимости от задачи может быть удобнее перенести маппинг внутрь функции получения данных.

→ Ссылка