Несколько URL-запросов к API без получения ошибок от urllib2 или запросов

Я пытаюсь получить данные из разных API. Они принимаются в формате JSON, сохраняются в SQLite и затем анализируются.

У меня проблема в том, что при отправке большого количества запросов я в конечном итоге получаю сообщение об ошибке, даже если я использую time.sleep между запросами.

Обычный подход

Мой код выглядит так, как показано ниже, где это будет внутри цикла, а URL, который нужно открыть, будет меняться:

base_url = 'https://www.whateversite.com/api/index.php?'
custom_url = 'variable_text1' + & + 'variable_text2' 

url = base_url + custom_urls #url will be changing

time.sleep(1)
data = urllib2.urlopen(url).read() 

Это выполняется тысячи раз внутри цикла. Проблема возникает после того, как сценарий был запущен некоторое время (до пары часов), затем я получаю следующие или похожие ошибки:

    data = urllib2.urlopen(url).read()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 127, in urlopen
    return _opener.open(url, data, timeout)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 404, in open
    response = self._open(req, data)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 422, in _open
    '_open', req)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 382, in _call_chain
    result = func(*args)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1222, in https_open
    return self.do_open(httplib.HTTPSConnection, req)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1184, in do_open
    raise URLError(err)
urllib2.URLError: <urlopen error [Errno 8] nodename nor servname provided, or not known>

или же

    uh = urllib.urlopen(url)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 87, in urlopen
    return opener.open(url)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 208, in open
    return getattr(self, name)(url)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 437, in open_https
    h.endheaders(data)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 969, in endheaders
    self._send_output(message_body)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 829, in _send_output
    self.send(msg)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 791, in send
    self.connect()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 1172, in connect
    self.timeout, self.source_address)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 553, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
IOError: [Errno socket error] [Errno 8] nodename nor servname provided, or not known

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

Из того, что я читал во многих различных темах о том, какой модуль лучше, я думаю, что для моих нужд все будет работать, и главный рычаг для выбора - это то, что он может открывать как можно больше URL. По моему опыту, urllib а также urllib2 лучше чем requests для этого, как requests разбился за меньшее время.

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

Возможные решения?

Я думал о комбинировании всех разных модулей. Это было бы:

  • Начните, например, с requests,
  • Через определенное время или при возникновении ошибки автоматически переключитесь на urllib2
  • По истечении определенного времени или при возникновении ошибки автоматически переключайтесь на другие модули (например, httplib2 или же urllib) или вернуться к requests
  • И так далее...

В

использование try .. except блок для обработки этого исключения, как предлагается здесь.

С

Я также читал об отправке нескольких запросов одновременно или параллельно. Я не знаю, как это работает, и может ли это быть полезным


Однако я не убежден ни в одном из этих решений.

Можете ли вы придумать какое-нибудь более элегантное и / или эффективное решение для устранения этой ошибки?

Я с Python 2.7

1 ответ

Решение

Даже если я не был убежден, я пытался реализовать try .. except блок и я вполне доволен результатом:

for url in list_of_urls:
    time.sleep(2)
    try:
        response = urllib2.urlopen(url)
        data = response.read()
        time.sleep(0.1)
        response.close() #as suggested by zachyee in the comments

        #code to save data in SQLite database

    except urllib2.URLError as e:
        print '***** urllib2.URLError: <urlopen error [Errno 8] nodename nor servname provided, or not known> *****'
        #save error in SQLite
        cur.execute('''INSERT INTO Errors (error_type, error_ts, url_queried)
        VALUES (?, ?, ?)''', ('urllib2.URLError', timestamp, url))
        conn.commit()
        time.sleep(30) #give it a small break

Скрипт действительно работает до конца.

Из тысяч запросов я получил 8 ошибок, которые были сохранены в моей базе данных с соответствующим URL. Таким образом, я могу попытаться получить эти URL снова после этого, если это необходимо.

Другие вопросы по тегам