Я пытаюсь получить данные из разных 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>
or
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
, я до сих пор думал об этих решениях:
Возможные решения?
A
Я думал объединить все разные модули. Это было бы:
- Начните, например, с
requests
. - Через определенное время или при возникновении ошибки автоматически переключаться на
urllib2
- Через определенное время или при возникновении ошибки автоматически переключаться на другие модули (например,
httplib2
илиurllib
) или обратно наrequests
- И так далее...
B
Используйте блок try .. except
для обработки этого исключения, как предлагается здесь< /а>.
C
Я также читал об отправке нескольких запросов одновременно или параллельно. Я не знаю, как именно это работает и может ли это быть действительно полезным.
Однако я не убежден ни в одном из этих решений.
Можете ли вы придумать более элегантное и/или эффективное решение для устранения этой ошибки?
Я использую Python 2.7
urlopen()
илиrequests
, чтобы закрыть соединение? - person zachyee   schedule 20.08.2016url = serviceurl + segment1 + '&' + segment2 + '&' + segment3
, где сегменты будут другими. Этот URL возвращает чистый JSON. - person J0ANMM   schedule 20.08.2016data
, правильно? - person J0ANMM   schedule 20.08.2016response = urllib.urlopen(url)
data = response.read()
response.close()
Как только он выйдет за рамки, он подходит для сборки мусора, но явное выполнение может помочь, поскольку вы пытаетесь получить доступ к большому количеству URL-адресов за небольшой промежуток времени. Еще лучше было бы использовать менеджер контекста (с ключевым словом). Дополнительная информация здесь: stackoverflow.com /вопросы/1522636/ - person zachyee   schedule 20.08.2016