0

Ruby アプリケーションで次の正規表現コードを使用して HTTP リンクを照合しようとしていますが、無効な出力が生成され、リンクの後ろにピリオド (場合によってはピリオドと単語) が追加され、Web 上でテストすると無効になります。

URL_PATTERN  = Regexp.new %r{http://[\w/.%-]+}i
<input>.to_s.scan( URL_PATTERN ).uniq

リンクをスキャンするための上記のコードに問題はありますか?

アプリからのコード:

require 'bundler/setup'
require 'twitter'

RECORD_LIMIT = 100
URL_PATTERN  = Regexp.new %r{http://[\w/.%-]+}i

def usage
  warn "Usage: ruby #{File.basename $0} <hashtag>"  
  exit 64
end

# Ensure that the hashtag has a hash symbol. This makes the leading '#'
# optional, which avoids the need to quote or escape it on the command line.
def format_hashtag(hashtag)  
  (hashtag.scan(/^#/).empty?) ? "##{hashtag}" : hashtag
end

# Return a sorted list of unique URLs found in the list of tweets.
def uniq_urls(tweets)  
  tweets.map(&:text).grep( %r{http://}i ).to_s.scan( URL_PATTERN ).uniq
end

def search(hashtag)  
  Twitter.search(hashtag, rpp: RECORD_LIMIT, result_type: 'recent')
end

if __FILE__ == $0 usage unless ARGV.size >= 1  
hashtag = format_hashtag(ARGV[0]) 
tweets = search(hashtag) 
puts uniq_urls(tweets)
end
4

3 に答える 3

1

車輪を再発明するのではなく、Ruby のURI.extractを使用してみませんか? Ruby に同梱されています。

ドキュメントから:

あらすじ

URI::extract(str[, スキーム][,&blk])

引数

str URI を抽出する文字列。
schemes URI マッチングを特定のスキームに制限します。

説明

文字列から URI を抽出します。ブロックが指定されている場合、一致するすべての URI を反復します。指定されたブロックまたは一致する配列の場合は nil を返します。
使用法

「uri」が必要

URI.extract("ここにテキスト http://foo.example.org/bla とここ mailto:test@example.com とここにも。")
# => ["http://foo.example.com/bla", "mailto:test@example.com"]

HTTP URL のみが必要な場合:

[3] (こじ開ける) main: 0> URI.extract("ここにテキスト http://foo.example.org/bla とここに mailto:test@example.com とここにも。", %w[http])
=> ["http://foo.example.org/bla"]
于 2012-05-29T19:26:09.747 に答える
1

問題は、単語文字、スラッシュ、パーセント記号、ハイフン (別名「マイナス」) 、およびピリオドの任意のシーケンスを無差別にチェックしているため、正規表現に末尾のピリオドが含まれることです。これは、URL が文末にある場合、実際には句読点である末尾のピリオドをキャッチします。また、ピリオドの後のスペースを省略した場合、それ以降はすべて – CodeGnome が正しく述べているように. 次のように末尾の句読点を除外することで、この問題を部分的に軽減できます (URL 以外の要素が続く句読点を直接キャッチすることに注意してください)。

http://\w+(?:[./%-]\w+)+$

ただし、これでも既存の URL の大部分が見落とされ、多くの無効なものが検出されます。URL は非常に複雑な獣です。完全な一致が必要な場合は、John Gruber が、http(s) だけでなく、現在 URL として使用されているあらゆるものに一致する正規表現を投稿しました。HTTPS バリアントを含む多数の Web 専用 URL をより厳密に一致させるには、最初に適切な形式のドメインがあることを確認し、クエリとフラグメント識別子をキャッチします。正規表現は次のようになります。

https?://[\w-]+(?:\.[\w-]+)+(?:/[\w-]+)*(?:(?:[./%?=&#-]\w+)+)?

–これでも無効なものをキャッチし、かなりの数の既存の URL を除外します (さらに、有効な URL のさらに大きな割合 – 上記でリンクした RFC を参照してください)。

于 2012-05-28T18:59:56.050 に答える