генерировать регулярное выражение Python во время выполнения, чтобы сопоставить числа от 'n' до бесконечности - PullRequest
1 голос
/ 05 марта 2011

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

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

URL моего сайта выглядят как http://foobar.com/page1.html, поэтому, как правило, регулярное выражение правила для перехода по каждой ссылке, как это, будет выглядеть примерно так:/page\d+\.html.

Но как мне написать регулярное выражение, чтобы оно соответствовало, например, странице 15 и более?Кроме того, поскольку я не знаю начальную точку заранее, как я могу сгенерировать это регулярное выражение во время выполнения?

Ответы [ 4 ]

3 голосов
/ 05 марта 2011

Почему бы не сгруппировать номер страницы, а затем проверить, правильно ли он указан:

>>> m=re.match("/page(\d+)\.html","/page18.html")
>>> if m:
    ID=int(m.groups()[0])
>>> ID > 15
True

Отредактировано:

Хорошо, поскольку вы хотите:

>>> def genRegex(n):
    return ''.join('[' + "0123456789"[int(d):] + ']' for d in str(n))

>>> genRegex(123)
'[123456789][23456789][3456789]'
2 голосов
/ 10 марта 2011

немного расширив ответ Каби:

def genregex(n):
    nstr = str(n)
    same_digit = ''.join('[' + "0123456789"[int(d):] + ']' for d in nstr)
    return "\d{%d,}|%s" % (len(nstr) + 1, same_digit)

Легко изменить, чтобы обрабатывать первые 0, если это происходит на вашем сайте. Но это кажется неправильным подходом.

У вас есть несколько других вариантов в терапии. Вероятно, вы используете SgmlLinkExtractor , и в этом случае проще всего передать собственную функцию в качестве аргумента ключевого слова process_value для выполнения пользовательской фильтрации.

Вы можете настроить CrawlSpider довольно сильно, но если он не подходит для вашей задачи, вам следует проверить BaseSpider

2 голосов
/ 05 марта 2011

Попробуйте это:

def digit_match_greater(n):
    digits = str(n)
    variations = []
    # Anything with more than len(digits) digits is a match:
    variations.append(r"\d{%d,}" % (len(digits)+1))
    # Now match numbers with len(digits) digits.
    # (Generate, e.g, for 15, "1[6-9]", "[2-9]\d")
    # 9s can be skipped -- e.g. for >19 we only need [2-9]\d.
    for i, d in enumerate(digits):
        if d != "9": 
            pattern = list(digits)
            pattern[i] = "[%d-9]" % (int(d) + 1)
            for j in range(i+1, len(digits)):
                pattern[j] = r"\d"
            variations.append("".join(pattern))
    return "(?:%s)" % "|".join("(?:%s)" % v for v in variations)

Оказалось, проще сделать так, чтобы оно совпадало с числами, большими, чем параметр, поэтому, если вы дадите ему 15, он вернет строку для совпадающих чисел от 16 и более, в частности ...

(?:(?:\d{3,})|(?:[2-9]\d)|(?:1[6-9]))

Затем вы можете подставить это в выражение вместо \d+, например:

exp = re.compile(r"page%s\.html" % digit_match_greater(last_page_visited))
0 голосов
/ 05 марта 2011
>>> import regex
>>> import random
>>> n=random.randint(100,1000000)
>>> n
435220
>>> len(str(n))
>>> '\d'*len(str(n))
'\\d\\d\\d\\d\\d\\d'
>>> reg='\d{%d}'%len(str(n))
>>> m=re.search(reg,str(n))
>>> m.group(0)
'435220'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...