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