Частичные совпадения в словаре - PullRequest
0 голосов
/ 27 февраля 2011

Предположим, у меня есть следующее словарное сопоставление доменных имен с его удобочитаемым описанием

domain_info = {"google.com" : "A Search Engine", 
               "facebook.com" : "A Social Networking Site", 
               "stackoverflow.com" : "Q&A Site for Programmers"}

Я хотел бы получить описание из response.url, которое возвращает абсолютный путь http://www.google.com/reader/view/

Мой текущий подход

url = urlparse.urlparse(response.url)
domain = url.netloc        # 'www.google.com'
domain = domain.split(".") # ['www', 'google', 'com']
domain = domain[-2:]       # ['google', 'com']
domain = ".".join(domain)  # 'google.com'
info = domain_info[domain]

кажется слишком медленным для большого количества вызовов, кто-нибудь может предложить альтернативный способ ускорить процесс?

Идеальное решение будет обрабатывать любой поддомен и нечувствительно к регистру

Ответы [ 4 ]

2 голосов
/ 27 февраля 2011

Что означает «слишком медленно для большого количества операций»? Это все еще будет работать в постоянное время (для каждого URL), и вы не можете стать лучше, чем это. Вышесказанное кажется вполне хорошим способом сделать это.

Если вам нужно, чтобы это было немного быстрее (но это не было бы ужасно быстрее), вы можете написать свое собственное регулярное выражение. Что-то вроде "[a-zA-Z]+://([a-zA-Z0-9.]+)". Это позволило бы получить полный домен, а не поддомен. Вам все равно нужно будет выполнить разбиение домена, если вы не можете использовать предпросмотр в регулярном выражении, чтобы получить только последние два сегмента. Обязательно используйте re.compile, чтобы сделать само регулярное выражение быстрым.

Обратите внимание, что domain[-2], вероятно, не будет тем, что вы хотите. Логика поиска подходящего «домена уровня компании» довольно сложна. Например, если домен google.com.au, это даст вам «com.au», что вряд ли будет тем, что вы хотите - вы, вероятно, хотите «google.com.au».

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

url = urlparse.urlparse(response.url)
domain = url.netloc        # 'www.google.com'
domain = domain.split(".") # ['www', 'google', 'com']
info = None
for i in range(len(domain)):
    subdomain = ".".join(domain[i:]) # 'www.google.com', 'google.com', 'com'
    try:
        info = domain_info[subdomain]
        break
    except KeyError:
        pass

С помощью приведенного выше кода вы найдете его, если он соответствует какому-либо поддомену. Что касается чувствительности к регистру, это легко. Убедитесь, что все ключи в словаре строчные, и примените .lower() к домену перед всей другой обработкой.

1 голос
/ 27 февраля 2011

Вы можете использовать часть работы, которую выполняет urlparse.Попробуйте поискать вещи напрямую с помощью netloc, которое он возвращает, и откатитесь на разделение / объединение, только если вы должны:

def normalize( domain ):
    domain = domain.split(".") # ['www', 'google', 'com']
    domain = domain[-2:]       # ['google', 'com']
    return ".".join(domain)  # 'google.com'


# caches the netlocs that are not "normal"
aliases = {}

def getinfo( url ):
    netloc = urlparse.urlparse(response.url).netloc

    if netloc in aliases:
        return domain_info[aliases[netloc]]

    if netloc in domain_info:
        return domain_info[netloc]

    main = normalize(netloc)
    if main in domain_info:
        aliases[netloc] = main
        return domain_info[netloc]

То же самое с кеширующей библиотекой:

from beaker.cache import CacheManager
netlocs = CacheManager(namespace='netloc')

@netlocs.cache()
def getloc( domain ):
    try:
        return domain_info[domain]
    except KeyError:
        domain = domain.split(".")
        domain = domain[-2:]
        domain = ".".join(domain)
        return domain_info[domain]

def getinfo( url ):
    netloc = urlparse.urlparse(response.url).netloc
    return getloc( netloc )

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

1 голос
/ 27 февраля 2011

Вы можете рассмотреть возможность извлечения домена без поддоменов с помощью регулярного выражения:

'http:\/\/([^\.]+\.)*([^\.][a-zA-Z0-9\-]+\.[a-zA-Z]{2,6})(\/?|\/.*)'

import re
m = re.search('http:\/\/([^\.]+\.)*([^\.][a-zA-Z0-9\-]+\.[a-zA-Z]{2,6})(\/?|\/.*)', 'http://www.google.com/asd?#a')
print m.group(2)
1 голос
/ 27 февраля 2011

Кажется, что urlparse.py в стандартной библиотеке Python 2.6 делает несколько вещей при вызове функции urlparse ().Может быть возможно ускорить процесс написания небольшого парсера URL, который делает только то, что абсолютно необходимо, и не болеесинтаксис доменных имен, это может дать некоторые идеи для парсера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...