繁体   English   中英

在运行时生成python正则表达式以将数字从'n'匹配为无限

[英]generate python regex at runtime to match numbers from 'n' to infinite

我正在使用scrapy来爬网网站并从中提取数据,scrapy使用基于正则表达式的规则来检查是否必须解析页面或必须遵循链接。

我正在为我的蜘蛛实现简历功能,因此它可以从上次访问的页面继续爬网。 为此,启动Spider时,我从数据库获得了最后一个链接。

我的网站url看起来像http://foobar.com/page1.html ,因此,通常,遵循这样的每个链接的规则的正则表达式将类似于/page\\d+\\.html

但是我如何编写一个正则表达式,使其与第15页或更多内容匹配? 另外,由于我事先不知道起点,我如何在运行时生成此正则表达式?

为什么不对页码进行分组,然后检查其是否合格:

>>> 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]'

尝试这个:

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))

扩展了Kabie的答案:

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

>>> 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'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM