@spiller1975
доберусь до самой сути

Как устранить ошибку «TooManyRedirects: Exceeded 30 redirects» при выполнении скрипта Python?

Здравствуйте.

Начинаю изучать Python, прошу помощи!
В интернете нашел нужный мне скрипт для управления модемом Huawei E5186 через встроенный API.
Использую Python 2.7 под Windows 7, все нужные модули установлены.
В процессе тестов нашел рабочий вариант в моей ситуации

вот текст скрипта
#!/usr/bin/env python

from __future__ import unicode_literals
#from PyCRC.CRC16 import CRC16

import requests
import re
import hashlib
import base64
import os, sys

def reboot(baseurl, session):
    data='<request><Control>1</Control></request>'
    r= session.post(baseurl + "api/device/control", data=data)
    
def login(baseurl, username, password):
    s = requests.Session()
    r = s.get(baseurl + "html/home.html")
    csrf_tokens = grep_csrf(r.text)
    headers_update(s.headers, csrf_tokens[1])
    data = login_data(username, password, str(csrf_tokens[1]))
    r = s.request('POST', baseurl + "api/user/login", data=data)
    s.headers.update({'__RequestVerificationToken': r.headers["__requestverificationtokenone"]})
    return s

def headers_update(dictbase, token):
    dictbase['Accept-Language'] = 'en-US'
    dictbase['Content-Type'] = 'application/x-www-form-urlencoded'
    dictbase['X-Requested-With'] = 'XMLHttpRequest'
    dictbase['__RequestVerificationToken'] = token
    dictbase['Cache-Control'] = 'no-cache'
    dictbase['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Version/8.0.8 Safari/600.8.9'
    
def grep_csrf(html):
    pat = re.compile(r".*meta name=\"csrf_token\" content=\"(.*)\"", re.I)
    matches = (pat.match(line) for line in html.splitlines())
    return [m.group(1) for m in matches if m]

def login_data(username, password, csrf_token):
    def encrypt(text):
        m = hashlib.sha256()
        m.update(text)
        return base64.b64encode(m.hexdigest())
    password_hash = encrypt(username + encrypt(password) + csrf_token)
    return '<?xml version "1.0" encoding="UTF-8"?><request><Username>%s</Username><Password>%s</Password><password_type>4</password_type></request>' % (username, password_hash)

baseurl = "http://192.168.1.1/"
username = "admin"
password = "admin"

if __name__ == "__main__":
    print "Trying to log in..."
    s = login(baseurl, username, password)
    print "Logged ! Trying to reboot..."
    reboot(baseurl, s)
</code</spoiler>>
Этот скрипт перезагружает устройство, он работает.

Мне нужны несколько другие возможности API, поэтому пытаюсь задействовать другие функции.
Для смены режима работы сети 4G роутера пытаюсь запускать 

<spoiler title="такой скрипт"><code lang="python">
import requests
import re
import hashlib
import base64
import os, sys

def changemode(baseurl, session):
    data='<request><NetworkMode>03</NetworkMode></request>'
    r= session.post(baseurl + "/api/net/net-mode", data=data)
    
    
def login(baseurl, username, password):
    s = requests.Session()
    r = s.get(baseurl + "html/home.html")
    csrf_tokens = grep_csrf(r.text)
    headers_update(s.headers, csrf_tokens[1])
    data = login_data(username, password, str(csrf_tokens[1]))
    r = s.request('POST', baseurl + "api/user/login", data=data)
    s.headers.update({'__RequestVerificationToken': r.headers["__requestverificationtokenone"]})
    return s

def headers_update(dictbase, token):
    dictbase['Accept-Language'] = 'en-US'
    dictbase['Content-Type'] = 'application/x-www-form-urlencoded'
    dictbase['X-Requested-With'] = 'XMLHttpRequest'
    dictbase['__RequestVerificationToken'] = token
    dictbase['Cache-Control'] = 'no-cache'
    dictbase['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Version/8.0.8 Safari/600.8.9'
    
def grep_csrf(html):
    pat = re.compile(r".*meta name=\"csrf_token\" content=\"(.*)\"", re.I)
    matches = (pat.match(line) for line in html.splitlines())
    return [m.group(1) for m in matches if m]

def login_data(username, password, csrf_token):
    def encrypt(text):
        m = hashlib.sha256()
        m.update(text)
        return base64.b64encode(m.hexdigest())
    password_hash = encrypt(username + encrypt(password) + csrf_token)
    return '<?xml version "1.0" encoding="UTF-8"?><request><Username>%s</Username><Password>%s</Password><password_type>4</password_type></request>' % (username, password_hash)

baseurl = "http://192.168.1.1/"
username = "admin"
password = "admin"

if __name__ == "__main__":
    s = login(baseurl, username, password)
    changemode(baseurl, s)
</code></spoiler>

Получая ошибку:

<code>Traceback (most recent call last):
  File "D:\scripts\morereboot.py", line 54, in <module>
    changemode(baseurl, s)
  File "D:\scripts\morereboot.py", line 14, in changemode
    r= session.post(baseurl + "/api/net/net-mode", data=data)
  File "C:\Python27\lib\site-packages\requests-2.22.0-py2.7.egg\requests\sessions.py", line 581, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "C:\Python27\lib\site-packages\requests-2.22.0-py2.7.egg\requests\sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Python27\lib\site-packages\requests-2.22.0-py2.7.egg\requests\sessions.py", line 668, in send
    history = [resp for resp in gen] if allow_redirects else []
  File "C:\Python27\lib\site-packages\requests-2.22.0-py2.7.egg\requests\sessions.py", line 165, in resolve_redirects
    raise TooManyRedirects('Exceeded %s redirects.' % self.max_redirects, response=resp)
TooManyRedirects: Exceeded 30 redirects.</code>

Поискал в сети, пишут какая-то проблема с заголовком User-Agent или с кукисами.

Подскажите как избавится от ошибки!
  • Вопрос задан
  • 131 просмотр
Пригласить эксперта
Ответы на вопрос 1
@crazywu
А разве там не инфити луп на changemode? Если я правильно понял, то эта функция вызывает редиррект. И получается, что это будет происходить до тех пор пока __name__ == "__main__". И, мне показалось, что __name__ не изменит значение во время выполнения changemode (могу ошибаться)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы