14 августа 2022 г.

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

Одна вещь, которой не хватает в Python, — это тип package.json, который есть в JS, где вы можете размещать там скрипты. Я полагаю, что мог бы обойти это с помощью библиотеки cli

В любом случае, что я думаю сделать, так это создать новую папку src/api/cluster_trends и превратить скрипт из тестового репозитория в маршрут в стандартном коде. Я заставлю его следовать структуре, аналогичной маршруту user.

Обратите внимание на __init__.py в корне src — сюда добавляются маршруты:

from fastapi import APIRouter
from api.user.v1.user import user_router as user_v1_router
router = APIRouter()
router.include_router(user_v1_router, prefix="/api/v1/users", tags=["User"])
__all__ = ["router"]

Итак, вот что я сделал:

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

К счастью, этот шаблонный репозиторий очень хорошо структурирован, поэтому у меня уже есть папка utils, чтобы поместить его в src/core/utils.

Код такой же, как и раньше для сериализатора

import json
from aylien_news_api import RepresentativeStory
from datetime import datetime
class CustomSerializer(json.JSONEncoder):
    """
    Extends json encoder to serialize custom aylien api objects, as well as datetime and 
    other pesky non-dict objects
    """
    def default(self, obj):
        if isinstance(obj, RepresentativeStory):
            return obj.to_dict()
        elif isinstance(obj, datetime):
            return obj.isoformat()

Для нового маршрута я сделаю запрос GET с одним входным параметром — кодом IPTC. Таким образом, чтобы получить конкретные кластеры тем, вы пойдете curl -X GET https://0.0.0.0:8000?iptc=0000543

Я начну с создания простого маршрута, который просто выводит код iptc, который также принимается в качестве параметра.

В стороне: одна вещь, которую я только что заметил в документации fastapi, это то, что синтаксис немного меняется в fastapi с Python 3.10… Python на самом деле не имеет LTS, как Node, но 3.9 примерно 2 года назад и имеет исправления безопасности для следующего 3 года, поэтому я думаю, что разумнее продолжать использовать 3.9, поскольку он немного более зрелый и, вероятно, имеет больше исправлений ошибок, а не пытаться перейти на последнюю версию Python.

В любом случае, вот первый набросок cluster_trends.py:

from typing import List
from fastapi import APIRouter
from core.utils.json_serializer import CustomSerializer
cluster_trends_router = APIRouter()
@cluster_trends_router.get("")
async def get_cluster_trends(iptc_code: str):
    return {"iptc_code": iptc_code}

Затем в src/api/__init__.py :

from fastapi import APIRouter
from api.user.v1.user import user_router as user_v1_router
from api.cluster_trends.v1.cluster_trends import cluster_trends_router as cluster_trends_v1_router
router = APIRouter()
router.include_router(user_v1_router, prefix="/api/v1/users", tags=["User"])
router.include_router(cluster_trends_v1_router, prefix="/api/v1/cluster-trends", tags=["ClusterTrends"])
__all__ = ["router"]

После этого звонок в почтальон получает то, что я хочу

Отлично, теперь давайте добавим исходный код, который потребует некоторых изменений, чтобы соответствовать контексту API.

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

А пока я просто выплюну ответ. Я чувствую, что он будет слишком большим для почтальона, поэтому я не буду отправлять весь JSON.

Аааааааааааааааааааааааааааааа у меня опять ограничение

Это начало происходить только тогда, когда я попытался написать ответ в файл… Я предполагаю, что они внедрили какой-то блокировщик, который не позволяет людям записывать данные, извлеченные непосредственно из SDK.

Для контекста здесь сохраняются данные

for cluster_id in cluster_ids:
    metadata = get_cluster_metadata(cluster_id)
    if metadata is not None:
        stories = get_top_stories(cluster_id)
        metadata["stories"] = stories
        
    else:
        print("{} empty".format(cluster_id))
with open(f'data/{IPTC_CODE}.json', 'w+') as f:
    json.dump(metadata, f, cls=CustomSerializer)

Думаю, это имеет смысл. Они не хотят, чтобы люди просто записывали свои данные в файлы

Или я что-то не так делаю, и где-то делаю лишние запросы? В любом случае мне нужно быть осторожным в следующий раз, когда мой лимит скорости будет продлен, что, согласно ответу, произойдет сегодня вечером.

'x-ratelimit-reset': '2022-08-14 21:47:00 +0000'

Я удалю дамп json в следующий раз, когда запущу код, чтобы посмотреть, так ли это.

В противном случае, другой API, который я собирался попробовать, — это NewsAPI. Вы получаете 100 бесплатных запросов в день. У этого не так много с точки зрения обогащения данных (анализ настроений, кластеризация и т. Д.), Насколько я понимаю, он в основном просто выполняет очень конкретный тематический поиск и делает это довольно хорошо, как это выглядит.

В любом случае, сегодня вечером это убило для меня атмосферу, так что вернусь к этому завтра.