我正在尝试为 Woofy 编写一个脚本(tl;dr 一个下载网络漫画的程序),但显然我的正则表达式找不到指向上一页的链接,根据 Expresso 的说法。我试图找到类似以下内容的内容:
<a href="http://70-seas.com/?p=1253" title="Prologue 01" class="previous-comic-link"><span>‹ Previous</span></a>
这因每个页面而异,URL 和标题更改为链接到前一页的任何内容,具有:
<ashref="http://70-seas.com/?p=[0-9]{4}"stitle="[.]*s[.]*s([.]*)?"sclass="previous-comic-link"><span>‹sPrevious</span></a>
(有时标题有三个词,有时有两个字。不过,他们总是把数字作为最后一个词。
鉴于我没有正则表达式的先前经验或正式培训,我不知道我做错了什么。任何帮助将不胜感激。
有几件事需要解决。
首先,看一下http://70-seas.com/?p=[0-9]{4}
部分。此处的/?
表示/
字符是可选的。要匹配要匹配文字?
字符的 URL。由于?
字符是一个正则表达式元字符,这使得某些内容是可选的,因此您需要对其进行转义以使其在字面上匹配。为此,请使用 ?
.因此,更新的部分变为 http://70-seas.com/?p=[0-9]{4}
.您还添加了 expresso
标记,因此您可以遍历模式树并发现此问题。
接下来,真正的问题出在这部分: title="[.]*s[.]*s([.]*)?"
.正则表达式中的方括号表示与其中任何字符匹配的字符类。[.]
的真正意思是"匹配'.字符",这不是你的意图。您可能想使用与任何字符匹配的.
元字符,但最终通过将其放置在字符类中来逐字匹配它。接下来,您将第三部分设置为可选,而您可能打算将s
包含在最后一个可选组中。考虑到这些要点,您应该使用:title=".*s.*(s.*)?"
.
这应该行得通。但是,它不是最好的正则表达式,使用 .*
对我来说通常是一个危险信号。 .
匹配任何角色,这是一种贪婪的模式,可能会消耗超出预期的消耗。最好尝试具体。如果要匹配字母数字字符,请改用w
。根据您的描述,您期望 1-3 个单词。这可以表示为w+(?:sw+){0,2}
。更干净,更容易理解。它表示我们正在匹配一个或多个字母数字字符,后跟一组非捕获(?:sw+)
这意味着再次匹配空格,然后匹配一个或多个字母数字字符。最后,我们将{0,2}
量词放在组的末尾,以指示我们要匹配该组 0-2 次。如果不需要捕获,(?:...)
语法使组不捕获,从而提高性能。
您还应该做的一件事是转义所有双引号。根据您使用的内容,它可能会也可能不会有所不同,但这是通常需要的。所以你的双引号会变成"
.
您现在应该有这样的模式:
<ashref="http://70-seas.com/?p=[0-9]{4}"stitle="w+(?:sw+){0,2}"sclass="previous-comic-link"><span>‹sPrevious</span></a>
这很好,但这可能更简单。每当您必须在双引号之间匹配某些内容时,只要您不需要匹配其中的任何项目以供以后引用,那么您可以使用 title="[^"]+"
来简化此操作。[^"]+
部分使用负字符类,该类由字符类开头的^
字符指示。它基本上匹配任何不是双引号的字符。一旦遇到标题末尾的双引号,匹配将终止。无需担心 1-3 个单词,因为您只想匹配标题的全部内容。
新模式变为:
<ashref="http://70-seas.com/?p=[0-9]{4}"stitle="[^"]+"sclass="previous-comic-link"><span>‹sPrevious</span></a>