• Как исправить 401 при парсинге?

    @AWEme
    Retard Soft Inc.
    Если я правильно понял, то авторизация требуется из-за неправильного токена. В ответ приходит зашифрованный джсон, накидал расшифровку, надеюсь не сломается.
    В вопросе вы пытаетесь получить ответ через "Реквизиты", но я сделал вариант через "Строка QR-кода". На сайте пример использования есть.
    Из внешних зависимостей aiohttp(можно заменить на requests) и pycryptodome
    Код
    import json
    import hashlib
    import asyncio
    import aiohttp
    from Crypto.Cipher import AES
    
    URL = "https://proverkacheka.com"
    API = "/api/v1/check/get"
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0",
        "Referer": "https://proverkacheka.com/",
        "Origin": "https://proverkacheka.com",
    }
    
    
    def compute_token(qrraw: str, qr: str) -> str:
        base = qrraw + qr
    
        d = "0"
        for i in range(10000):
            h = hashlib.md5((base + (d := str(i))).encode()).hexdigest()
            if len(h.split("0")) - 1 > 4:
                break
        return "0." + d
    
    
    async def get_crypted_json(qrraw: str, qr: str) -> bytes:
        form = aiohttp.FormData()
        form.add_field(name="qrraw", value=qrraw)
        form.add_field(name="qr", value=qr)
        form.add_field(name="token", value=compute_token(qrraw, qr))
    
        async with aiohttp.ClientSession(headers=headers) as client:
            # Получаем куки
            await client.get(URL)
    
            response = await client.post(URL + API, data=form, headers={"Cookie": "ENGID=1.1"})
    
            if "+crypto" not in response.headers["Content-Type"]:
                raise ValueError("Invalid token")
    
            return await response.read()
    
    
    async def main() -> None:
        basekey = "38s91"
        decryptkey = "f65nm"
    
        qrraw = "t=20201017T1923&s=1498.00&fn=9282440300669857&i=25151&fp=1186123459&n=1"
        qr = "3"
        crypted_json = await get_crypted_json(qrraw, qr)
    
        crypted_data, nonce = crypted_json[:-12], crypted_json[-12:]
        key = hashlib.sha256((basekey + decryptkey).encode()).digest()
    
        cipher = AES.new(key=key, mode=AES.MODE_GCM, nonce=nonce)
        decrypted_data = cipher.decrypt(crypted_data)
    
        # В plain_text присутствует какие-то лишние символы на конце, скорее всего паддинг для зашифровки. Не проверял.
        plain_text = decrypted_data.decode(errors="ignore")
    
        # Отрезаем лишние символы справа
        pt = plain_text[:plain_text.rfind("}") + 1]
    
        with open("decoded.json", "wt", encoding="utf-8") as fp:
            loaded = json.loads(pt)
            json.dump(loaded, fp, ensure_ascii=False, indent=4)
    
    
    if __name__ == "__main__":
        asyncio.run(main())
    Ответ написан
    1 комментарий