2012-07-11 129 views
2

YouTube視頻ID我從這裏以下的正則表達式:https://stackoverflow.com/a/10405818/924999斯卡拉 - 從URL

val regex = """/https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube\.com(?:\/embed\/|\/v\/|\/watch\?v=|\/ytscreeningroom\?v=|\/feeds\/api\/videos\/|\/user\S*[^\w\-\s]|\S*[^\w\-\s]))([\w\-]{11})[?=&+%\w-]*/ig;""".r 

我試圖提取YouTube視頻網址與視頻ID:

val url = "http://www.youtube.com/watch?v=XrivBjlv6Mw" 

url match { 

    case regex(result) => result 

    case _ => null 

} 

然而,似乎總是返回null,有什麼我失蹤或需要做不同?提前任何幫助

謝謝,非常感謝:)

+7

請不要在Scala中使用'null'。如果視頻ID合法可以或不可以存在,那麼它應該是一個'Option [String]',返回'Some(result)'和'None'。如果正則表達式失敗總是一個硬錯誤,那麼在默認情況下拋出一個異常(或者如果你想對它有很強的功能,可以使用'Either')。 – 2012-07-11 10:55:40

+0

感謝您的提示,你有任何想法,爲什麼正則表達式匹配不會返回結果? – jhdevuk 2012-07-11 11:14:00

+0

不怕;調試既沒有評論也沒有解釋性分解的192字符正則表達式不是我的一杯茶。由於輸出只是一個布爾值(即「不匹配」),解決這個問題的唯一方法是將正則表達式分解成更小的部分,直到找到它失敗的原因爲止 - 這主要是* work *,並且不需要很多知識/見解等等。所以不用謝謝。 – 2012-07-11 12:04:02

回答

4

,你必須是php風格的正則表達式,而不是Java風格的正則表達式 - 例如,請注意0​​標誌在結尾處。

所以你只需要編輯了一下:

val youtubeRgx = """https?://(?:[0-9a-zA-Z-]+\.)?(?:youtu\.be/|youtube\.com\S*[^\w\-\s])([\w \-]{11})(?=[^\w\-]|$)(?![?=&+%\w]*(?:[\'"][^<>]*>|</a>))[?=&+%\w-]*""".r 

我測試了所有可能的YouTube網址,和它的作品。例如:

scala> youtubeRgx.pattern.matcher("http://www.youtube.com/watch?v=XrivBjlv6Mw").matches 
res23: Boolean = true 

,並提取值:

"http://www.youtube.com/watch?v=XrivBjlv6Mw" match { 
    case youtubeRgx(a) => Some(a) 
    case _ => None 
} 
res33: Option[String] = Some(XrivBjlv6Mw) 

這是一個遺憾的是,Java不允許在正則表達式正確的意見,所以我做了我所能做:

val youtubeRgx = """https?://   # Required scheme. Either http or https. 
        |(?:[0-9a-zA-Z-]+\.)? # Optional subdomain. 
        |(?:    # Group host alternatives. 
        | youtu\.be/  # Either youtu.be, 
        || youtube\.com # or youtube.com followed by 
        | \S*    # Allow anything up to VIDEO_ID, 
        | [^\w\-\s]  # but char before ID is non-ID char. 
        |)     # End host alternatives. 
        |([\w\-]{11})  # $1: VIDEO_ID is exactly 11 chars. 
        |(?=[^\w\-]|$)  # Assert next char is non-ID or EOS. 
        |(?!    # Assert URL is not pre-linked. 
        | [?=&+%\w]*  # Allow URL (query) remainder. 
        | (?:    # Group pre-linked alternatives. 
        | [\'"][^<>]*> # Either inside a start tag, 
        | | </a>   # or inside <a> element text contents. 
        | )    # End recognized pre-linked alts. 
        |)     # End negative lookahead assertion. 
        |[?=&+%\w-]*  # Consume any URL (query) remainder. 
        |""".stripMargin.replaceAll("\\s*#.*\n", "").replace(" ","").r 

(改編from @ ridgerunner的答案在這裏:find all youtube video ids in string

+0

哇,非常感謝你的出色幫助:)我在這裏收到很長時間的最好的答案之一:) – jhdevuk 2012-07-11 13:30:23

+0

@sirjamm - 不客氣:) – Rogach 2012-07-11 14:34:07

+0

@Rogach - 您可以添加評論在如果以(?x)開頭,則爲正則表達式。 – sellmerfud 2012-07-11 21:53:50

0

一個更簡單的方法:

scala> val url = "http://www.youtube.com/watch?v=XrivBjlv6Mw" 
url: java.lang.String = http://www.youtube.com/watch?v=XrivBjlv6Mw 

scala> val regex = "v=[\\w]*"r 
regex: scala.util.matching.Regex = v=[\w]* 

scala> for (x <- regex findFirstIn url) yield x.replace("v=","") 
res3: Option[java.lang.String] = Some(XrivBjlv6Mw) 
+1

按照http://stackoverflow.com/questions/5830387/php-regex-find-all-youtube-video-ids-in-string/10405818#10405818,這不會趕上大多數IDS。 – Rogach 2012-07-11 12:00:03

0

First Scala接受Java風格的正則表達式。如果你提供斜槓,那麼它們是模式的一部分,而不是分隔符。此外,標誌必須爲每個組指定,而不是在正則表達式之後。

第二,要匹配case regex(result),您必須在您的模式中定義匹配組。你必須將視頻ID分組爲匹配模式 - 我只是不知道這是否是過度複雜的模式。