Я пытаюсь запустить веб-сервис, который действительно требует проверки баз данных whois. То, что я делаю прямо сейчас, ужасно, и я хотел бы избежать этого, насколько это возможно: я вызываю команду gwhois и анализирую ее вывод. Уродливый.
Я немного поискал, чтобы попытаться найти питонический способ решения этой задачи. Обычно у меня почти ничего нет - ссылка на этот старый список обсуждений имеет способ проверить, существует ли домен. Совсем не то, что я искал ... Но все же это был лучший ответ, который мне дал Google - все остальное - просто куча неотвеченных вопросов.
Кому-нибудь из вас удалось запустить какой-нибудь метод? Я был бы очень признателен за несколько советов, или мне просто сделать это с открытым исходным кодом, сесть и написать что-нибудь сам? :)






Другой способ сделать это - использовать модуль urllib2 для анализа службы whois какой-либо другой страницы (существует множество подобных сайтов). Но это кажется еще большим взломом, чем то, что вы делаете сейчас, и даст вам зависимость от того, какой сайт whois вы выберете, а это плохо.
Ненавижу это говорить, но если вы не хотите повторно реализовать whois в своей программе (что означало бы заново изобретать колесо), запуск whois в ОС и анализ вывода (то есть то, что вы делаете сейчас) кажется правильным способ сделать это.
Разбор другой веб-страницы не будет таким плохим (при условии, что их html не будет очень плохим), но на самом деле он привяжет меня к ним - если они не работают, я упал :)
На самом деле я нашел на sourceforge какой-то старый проект: rwhois.py. Что меня немного пугает, так это то, что их последнее обновление датировано 2003 годом. Но это может показаться хорошим местом для начала повторной реализации того, что я делаю прямо сейчас ... Что ж, я все равно чувствовал себя обязанным опубликовать ссылку на этот проект, просто для дальнейших справок.
Что действительно изменилось в whois за последние 5 лет. Рискну предположить, что «немногое». Я все еще думаю, что вы заново изобретаете колесо. Мой идеальный ответ: используйте то, что работает для вас сейчас, если вы не чувствуете в этом реальной проблемы.
Нет ничего плохого в том, чтобы использовать утилиту командной строки, чтобы делать то, что вы хотите. Если вы поместите красивую оболочку вокруг службы, вы можете реализовать внутреннюю часть, как хотите! Например:
class Whois(object):
_whois_by_query_cache = {}
def __init__(self, query):
"""Initializes the instance variables to defaults. See :meth:`lookup`
for details on how to submit the query."""
self.query = query
self.domain = None
# ... other fields.
def lookup(self):
"""Submits the `whois` query and stores results internally."""
# ... implementation
Теперь, независимо от того, используете ли вы свой собственный с помощью urllib, оборачиваете ли вы утилиту командной строки (как вы это делаете) или импортируете стороннюю библиотеку и используете ее (например, ты говоришь), этот интерфейс остается прежним.
Такой подход вообще не считают уродливым - иногда командные утилиты делают то, что вы хотите, и вы должны иметь возможность использовать их. Если скорость оказывается узким местом, ваша абстракция делает процесс перехода на нативную реализацию Python прозрачным для вашего клиентского кода.
Практичность превосходит чистоту - вот что такое Pythonic. :)
Да, я знаю. Но использование слишком большого количества системных инструментов и создание оболочек вокруг них затрудняет, скажем так, миграцию приложения в другую систему ... Но я думаю, что я буду придерживаться того, что у меня есть сейчас, если это сработает;)
С хорошим барьером абстракции вы можете реализовать его в любое удобное время! «Сейчас лучше, чем никогда, Хотя никогда не бывает лучше, чем прямо сейчас». :)
@kender: так проще! Вам просто нужно переключить внутреннее устройство с gwhois на Xwhois. Если вы также хотите сохранить старую реализацию, вы можете расширить старый класс и просто переопределить, например, метод поиска.
Это совершенно неверно! Не выполняйте раскладку для выполнения команды whois. По крайней мере, просто откройте сокет TCP на порт 43 и прочтите RFC3912. Это не имеет ничего общего с практичностью, запуск такой команды оболочки только вызовет ряд проблем с безопасностью и производительностью. Это не лучший способ решить проблему.
Я не знаю, делает ли gwhois что-то особенное с выводом сервера; однако вы можете просто подключиться к серверу whois через порт whois (43), отправить свой запрос, прочитать все данные в ответе и проанализировать их. Чтобы немного облегчить жизнь, вы можете использовать класс telnetlib.Telnet (даже если протокол whois намного проще, чем протокол telnet) вместо простых сокетов.
Сложные части:
настоящая проблема не в запросах серверов, а в разборе их выходных данных. к сожалению, формат, который они возвращают, сильно меняется между серверами. Одна из строк, время истечения срока, может выглядеть так: Дата истечения: 05-сен-2009 15:24:49 UTC или истекает: 26-дек-14, или некоторые серверы не предоставляют это вообще.
Они оба являются частью проблемы. В моем случае было достаточно сложно найти правильный (авторитетный) whois-сервер в каждом случае. Разбор данных не был таким сложным, поскольку нас интересовали в основном родительские подсети, поэтому с помощью небольших проб и ошибок мы закончили. Не могу предоставить код, извините.
import socket
socket.gethostbyname_ex('url.com')
если он возвращает ошибку, вы знаете, что он не зарегистрирован ни в одном DNS
-1 = Выполнение DNS-запроса не то же самое, что и Whois-запрос
вот готовое решение, которое мне подходит; написан для Python 3.1 (при обратном переносе на Py2.x особое внимание уделяйте различиям между байтами и текстом Unicode). ваша единственная точка доступа - это метод DRWHO.whois(), который ожидает передачи доменного имени; затем он попытается разрешить имя, используя поставщика, настроенного как DRWHO.whois_providers[ '*' ] (более полное решение может различать поставщиков в соответствии с доменом верхнего уровня). DRWHO.whois() вернет словарь с единственной записью text, которая содержит текст ответа, отправленный обратно сервером WHOIS. Опять же, более полное решение могло бы затем попытаться проанализировать текст (который должен выполняться отдельно для каждого поставщика, поскольку стандартного формата не существует) и вернуть более структурированный формат (например, установить флаг available, который указывает, является ли домен выглядит доступным). радоваться, веселиться!
##########################################################################
import asyncore as _sys_asyncore
from asyncore import loop as _sys_asyncore_loop
import socket as _sys_socket
##########################################################################
class _Whois_request( _sys_asyncore.dispatcher_with_send, object ):
# simple whois requester
# original code by Frederik Lundh
#-----------------------------------------------------------------------
whoisPort = 43
#-----------------------------------------------------------------------
def __init__(self, consumer, host, provider ):
_sys_asyncore.dispatcher_with_send.__init__(self)
self.consumer = consumer
self.query = host
self.create_socket( _sys_socket.AF_INET, _sys_socket.SOCK_STREAM )
self.connect( ( provider, self.whoisPort, ) )
#-----------------------------------------------------------------------
def handle_connect(self):
self.send( bytes( '%s\r\n' % ( self.query, ), 'utf-8' ) )
#-----------------------------------------------------------------------
def handle_expt(self):
self.close() # connection failed, shutdown
self.consumer.abort()
#-----------------------------------------------------------------------
def handle_read(self):
# get data from server
self.consumer.feed( self.recv( 2048 ) )
#-----------------------------------------------------------------------
def handle_close(self):
self.close()
self.consumer.close()
##########################################################################
class _Whois_consumer( object ):
# original code by Frederik Lundh
#-----------------------------------------------------------------------
def __init__( self, host, provider, result ):
self.texts_as_bytes = []
self.host = host
self.provider = provider
self.result = result
#-----------------------------------------------------------------------
def feed( self, text ):
self.texts_as_bytes.append( text.strip() )
#-----------------------------------------------------------------------
def abort(self):
del self.texts_as_bytes[:]
self.finalize()
#-----------------------------------------------------------------------
def close(self):
self.finalize()
#-----------------------------------------------------------------------
def finalize( self ):
# join bytestrings and decode them (witha a guessed encoding):
text_as_bytes = b'\n'.join( self.texts_as_bytes )
self.result[ 'text' ] = text_as_bytes.decode( 'utf-8' )
##########################################################################
class DRWHO:
#-----------------------------------------------------------------------
whois_providers = {
'~isa': 'DRWHO/whois-providers',
'*': 'whois.opensrs.net', }
#-----------------------------------------------------------------------
def whois( self, domain ):
R = {}
provider = self._get_whois_provider( '*' )
self._fetch_whois( provider, domain, R )
return R
#-----------------------------------------------------------------------
def _get_whois_provider( self, top_level_domain ):
providers = self.whois_providers
R = providers.get( top_level_domain, None )
if R is None:
R = providers[ '*' ]
return R
#-----------------------------------------------------------------------
def _fetch_whois( self, provider, domain, pod ):
#.....................................................................
consumer = _Whois_consumer( domain, provider, pod )
request = _Whois_request( consumer, domain, provider )
#.....................................................................
_sys_asyncore_loop() # loops until requests have been processed
#=========================================================================
DRWHO = DRWHO()
domain = 'example.com'
whois = DRWHO.whois( domain )
print( whois[ 'text' ] )
Посмотри на это: http://code.google.com/p/pywhois/
pywhois - модуль Python для получения информации WHOIS доменов
Цель: - Создайте простой импортируемый модуль Python, который будет создавать проанализированные данные WHOIS для данного домена. - Возможность извлекать данные для всех популярных TLD (com, org, net, ...) - Запросы к серверу WHOIS напрямую, а не через промежуточную веб-службу, как это делают многие другие. - Работает с Python 2.4+ и без внешних зависимостей
Пример:
>>> import pywhois
>>> w = pywhois.whois('google.com')
>>> w.expiration_date
['14-sep-2011']
>>> w.emails
['[email protected]',
'[email protected]',
'[email protected]',
'[email protected]']
>>> print w
...
Можно ли это установить с помощью pip? Существует пакет pywhois 0.1, но, похоже, это не то же самое.
@samwize (и другие, желающие об этом знать) см .: stackoverflow.com/questions/11578943/error-when-using-pywhoi s
Вот клиент whois, повторно реализованный на Python: http://code.activestate.com/recipes/577364-whois-client/
Нашел этот вопрос в процессе собственного поиска библиотеки whois для Python.
Не знаю, согласен ли я с ответом cdleary, что использование библиотеки, которая обертывает команда - всегда лучший выход, но я могу понять его причины, по которым он это сказал.
Pro: cmd-line whois выполняет всю тяжелую работу (вызовы сокетов, синтаксический анализ и т. д.)
Минусы: не переносится; модуль может не работать в зависимости от базовой команды whois. Медленнее, так как запускается команда и, скорее всего, оболочка в дополнение к команде whois. Затронуто, если не UNIX (Windows), другой UNIX, старый UNIX или старая команда whois
Я ищу модуль whois, который может обрабатывать поиск IP-адресов whois, и меня не интересует кодирование моего собственного клиента whois.
Вот модули, которые я (слегка) опробовал, и дополнительная информация о них:
pywhoisapi:
BulkWhois
pywhois:
python-whois:
whoisclient - форк python-whois
Обновление: в итоге я использовал pywhoisapi для обратного поиска IP, который я делал
Нет, не следует запускать команду whois из своей программы. Whois - это очень простой протокол для реализации, просто откройте сокет TCP на порт 43 и прочтите RFC3912.