Я получил эту функцию для извлечения данных из XML (внутренняя сеть, я не могу указать URL-адрес по соображениям безопасности):
def crawl_and_get_data(url, keys, param1, param2, param3):
r = requests.get(url, auth = HTTPDigestAuth(keys[0], keys[1]))
xml_url = 'http://www.sitetogetdata.com/xml/?param1=' + param1 + '¶m2=' + param2 + '¶m3=' + param3
res = requests.get(xml_url, auth = HTTPDigestAuth(keys[0], keys[1]))
xml = res.text
return xml
Я хочу, чтобы эта функция работала в цикле, который принимает param1, param2 и param3.
frames = []
for i in range(len(table_with_params)):
try:
param1 = int(table_with_params.loc[i, 'param1'])
param2 = int(table_with_params.loc[i, 'param2'])
param3 = int(table_with_params.loc[i, 'param3'])
data = crawl_and_get_data(url, keys, param1, param2, param3)
frames.append(data)
except TypeError:
print('Whoops, something is wrong with this request.')
continue
Для большинства случаев это работает, но для некоторых конкретных случаев это не так. После выполнения я снова пытаюсь получить данные, но вне цикла, и это работает.
data = crawl_and_get_data(url, keys, problematic_param1, problematic_param2, problematic_param3)
# it works!
Есть намеки на это? Заранее спасибо.
Обновлено: пропустив обработку исключения, возвращается ошибка:
TypeError: cannot convert the series to <class 'int'>
Эта ошибка не возникает, когда функция выходит из цикла.
можешь поделиться кодом и ошибкой
@Alderven, это ошибка типа, возникающая из-за приведения int в параметрах. Пиюш, код уже предоставлен.
Пожалуйста, опубликуйте свой код ошибки полностью в op.






Существует так много причин, по которым HTTP-запрос может завершиться неудачно, что иногда это чудо, поэтому вам лучше быть готовым к неудачному запросу. При этом ваша проблема может быть на самом деле совершенно в другом месте, и ваша (довольно плохая) обработка исключений не позволяет вам получить какую-либо подсказку.
Ваша первая проблема здесь заключается в том, что ваш блок try слишком велик, вы хотите ограничить блок try строго необходимым. Вторая проблема заключается в том, что вы полностью игнорируете фактическое исключение и просто печатаете совершенно бесполезное сообщение.
В настоящее время в вашем блоке try есть в основном три отдельные части: подготовка аргумента запроса, выполнение самого запроса (на самом деле 2 запроса) и выполнение каких-либо действий с результатом. Каждая из этих частей может генерировать свои собственные особые исключения, поэтому правильной схемой обработки исключений будет размещение каждой части в отдельном блоке try (или, по крайней мере, вне других блоков try, если вы не ожидаете ничего особенного — «сделать что-то с частью результата», являющейся просто frames.append(data), на самом деле это не гарантирует блок try/except). IOW, вы хотите что-то вроде этого:
try:
param1 = int(table_with_params.loc[i, 'param1'])
param2 = int(table_with_params.loc[i, 'param2'])
param3 = int(table_with_params.loc[i, 'param3'])
except TypeError as e:
print("invalid source value at row {} : {}".format(i, e))
continue
try:
data = crawl_and_get_data(url, keys, param1, param2, param3)
вы НЕ должны получать здесь TypeError - теоретически, то есть см. ниже, что может быть вашей реальной проблемой
except RequestError as e:
print("Failed request for row {} : {}".format(i, e))
continue
frames.append(data)
Обратите внимание, что использование модуля logging было бы лучше, особенно потому, что он знает, как правильно регистрировать полную трассировку ошибок (которая чаще всего содержит очень ценную информацию об отладке).
Также обратите внимание, что:
def crawl_and_get_data(url, keys, param1, param2, param3):
r = requests.get(url, auth = HTTPDigestAuth(keys[0], keys[1]))
если цель состоит в том, чтобы войти в систему, а URL-адрес постоянен во внешнем (вызывающем) цикле, вы можете захотеть вместо этого посмотрите на сеансы запросов, это может вдвое уменьшить количество запросов. В противном случае это пустая трата времени, полосы пропускания и циклов процессора для вас И целевого сервера. Будьте добры к владельцу сервера.
xml_url = 'http://www.sitetogetdata.com/xml/?param1=' + param1 + '¶m2=' + param2 + '¶m3=' + param3
res = requests.get(xml_url, auth = HTTPDigestAuth(keys[0], keys[1]))
А теперь вот источник для TypeError (при условии, что то, что вы разместили, является вашим реальным кодом или достаточно похожим): вы явно конвертируете значения параметров в int в коде вызывающего объекта, а теперь пытаетесь объединить эти целые числа со строками. Это не работает и действительно вызывает TypeError (по очень веским причинам — языки, которые молча преобразуют несовместимые типы, сломаны по дизайну).
Как правило, для таких операций лучше использовать форматирование строк, чем конкатенацию строк, например:
xml_url = '...?param1 = {}¶m2 = {}¶m3 = {}'.format(param1, param2, param3)
который не только более удобочитаем, но и вызывает str() (или соответствующую функцию формата в зависимости от спецификатора формата), избегая TypeError.
НО есть и другие ловушки со строками HTTP-запросов и python-requests уже знает, как правильно создать действительную строку запроса из словаря, поэтому вам действительно следует использовать:
res = requests.get(url, params = {"param1": param1, "param2": param2, "param3": param3}, ....)
Бруно, спасибо за отзыв. Что касается конкретно второй проблемы, я только что изменил сообщение, чтобы опубликовать его здесь, но на самом деле оригинал звучит так: «Существует проблема с типом param1, param2 и param3». По поводу пробных блоков тоже хороший отзыв. Я отредактировал вопрос и добавил ошибку, которая теперь кажется мне проблемой кастинга.
Ошибка не исходит от сканирования. Она находится в следующих строках:
param1 = int(table_with_params.loc[i, 'param1'])
param2 = int(table_with_params.loc[i, 'param2'])
param3 = int(table_with_params.loc[i, 'param3'])
Одна из этих строк возвращает объект серии pandas, который нельзя привести к типу int. Извините за форматирование, так как я новичок в stackoverflow и не знаю, как правильно форматировать код.
Спасибо
Спасибо за ответ, вы правы. Я бы принял ваш ответ, но ответ Бруно более полный и также упоминает кастинг. Не беспокойтесь о форматировании, я тоже новичок в SO. :)
Какая у вас ошибка?