2016-06-28 7 views
1

たとえば、pageからTwitterのURLを取得しようとしています。しかし、私の結果はnilです。私は正規表現があまりにも悪くないと確信していますが、コードが失敗します。ここにあります:Ruby - Regexを使用して任意のhtmlページからTwitterのURLを照合

doc = `(curl --url "http://www.rabbitreel.com/")` 
twitter_url = ("/^(?i)[http|https]+:\/\/(?i)[twitter]+\.(?i)(com)\/?\S+").match(doc) 
puts twitter_url 
# => nil 

多分私は正規表現構文を誤解しました。私の最初のアイデアはシンプルでした:私は通常のTwitterのURL構造に一致させたかったのです。私は正規表現をテストするためにhttp://rubular.comを試してみましたが、TwitterのURLを入力したときにはうまくいきました。

答えて

1

http://ruby-doc.org/core-2.2.0/String.html#method-i-match

あなたが上で試合を呼び出しているオブジェクトを使用すると、パースしている文字列であること、およびパラメータが正規表現パターンでなければならないことを示しています。何かあれば、あなたが呼び出す必要があります:

doc.match("/^(?i)[http|https]+:\/\/(?i)[twitter]+\.(?i)(com)\/?\S+") 

それは直接文字列ではなく、外の情報を取得するために別のステップを必要とするMatchDataを提供するので、私は、

doc[/your_regex/] 

構文を好みます。

Regexenのために、私はいつもできるだけ単純開始しようとし

[3] pry(main)> doc[/twitter/] 
=> "twitter" 
[4] pry(main)> doc[/twitter\.com/] 
=> "twitter.com" 
[5] pry(main)> doc[/twitter\.com\//] 
=> "twitter.com/" 
[6] pry(main)> doc[/twitter\.com\/\//] #OOPS. One \/ too many 
=> nil 
[7] pry(main)> doc[/twitter\.com\//] 
=> "twitter.com/" 
[8] pry(main)> doc[/twitter\.com\/\S+/] 
=> "twitter.com/rabbitreel\"" 
[9] pry(main)> doc[/twitter\.com\/[^"]+/] 
=> "twitter.com/rabbitreel" 
[10] pry(main)> doc[/http:\/\/twitter\.com\/[^"]+/] 
=> nil 
[11] pry(main)> doc[/https?:\/\/twitter\.com\/[^"]+/] 
=> "https://twitter.com/rabbitreel" 
[12] pry(main)> doc[/https?:\/\/twitter\.com\/[^" ]+/] 
=> "https://twitter.com/rabbitreel" 
[13] pry(main)> doc[/https?:\/\/twitter\.com\/\w+/] #DONE 
=> "https://twitter.com/rabbitreel" 

EDIT: は確かに、Regexenは、HTML文書全体を解析することはできません。 ここでは、Twitter URLの最初の出現箇所を探したいだけです。したがって、要求に応じて、可能な入力と選択されたプラットフォームに応じて、Regexpを使用することができます。

ノコギリは巨大な宝石ですので、インストールすることができない場合があります。

この事実から独立して、返されたStringが実際に正しいTwitter URLであることを確認することは非常に良い考えです。

私はこの正規表現だと思う:

/https?:\/\/twitter\.com\/\w+/ 

が安全です。

[31] pry(main)> malicious_doc = "https://twitter.com/[email protected]" 
=> "https://twitter.com/[email protected]" 
[32] pry(main)> malicious_doc[/https?:\/\/twitter\.com\/\w+/] 
=> "https://twitter.com/userid" 

ノコギリを使用しても、悪意のある入力を確認することはできません。 @mudasobwaから 提案された解決策は興味深いですが、まだ安全ではありません。

[33] pry(main)> Nokogiri::HTML('<html><body><a href="http://maliciouswebsitethatisnottwitter.com/">Link</a></body></html>').css('a').map { |e| e.attributes.values.first.value }.select {|e| e =~ /twitter.com/ } 
=> ["http://maliciouswebsitethatisnottwitter.com/"] 
+1

感謝。私はあなたが一歩一歩行く方法が好きです! – Eric

0

一つは、HTMLやhere is whyを解析するために正規表現を使用しないでください。

以下

Nokogiri HTML構文解析ライブラリを使用して堅牢なソリューションです:

require 'nokogiri' 
doc = Nokogiri::HTML(`(curl --url "http://www.rabbitreel.com/")`) 
doc.css('a').map { |e| e.attributes.values.first.value } 
      .select {|e| e =~ /twitter.com/ } 
#⇒ [ 
# [0] "https://twitter.com/rabbitreel", 
# [1] "https://twitter.com/rabbitreel" 
# ] 

あるいは、XPathので:感謝@EricDuminil入力用

require 'nokogiri' 
doc = Nokogiri::HTML(`(curl --url "http://www.rabbitreel.com/")`) 
doc.xpath('//a[contains(@href, "twitter.com")]') 
    .map { |e| e.attributes['href'].value } 
+0

助けてくれてありがとうございます@ mudasobwa、私もノコギリ方法を試してみます:) – Eric

+1

あなたは正規表現で自分の足を撃つことは自由です、決定は常にあなた次第です。しかし、誰も専門的な純粋なルビーの開発者はその目的のために正規表現を使用しないことに言及する価値がある。 – mudasobwa

+0

敬意をもって、あなたはRegexpで足に自分を撃った。 '/ twitter.com /'は '' http://maliciouswebsitethatisnottwitter.com/''にマッチし、 '' http://maliciouswebsite.com/twitter/com "' –

関連する問題