Использование NSRegularExpression для извлечения URL-адресов на iPhone - PullRequest
12 голосов
/ 06 марта 2012

Я использую следующий код в своем приложении для iPhone, взятый из здесь , чтобы извлечь все URL из чередующегося HTML-кода.

Я могу извлечь только первыйURL, но мне нужен массив, содержащий все URL.Мой NSArray не возвращает строки NSStrings для каждого URL-адреса, но только описания объектов.

Как мне заставить мой arrayOfAllMatches возвращать все URL-адреса в виде строк NSStrings?

-(NSArray *)stripOutHttp:(NSString *)httpLine {

// Setup an NSError object to catch any failures
NSError *error = NULL;  

// create the NSRegularExpression object and initialize it with a pattern
// the pattern will match any http or https url, with option case insensitive

NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?" options:NSRegularExpressionCaseInsensitive error:&error];

// create an NSRange object using our regex object for the first match in the string httpline
NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:httpLine options:0 range:NSMakeRange(0, [httpLine length])];

NSArray *arrayOfAllMatches = [regex matchesInString:httpLine options:0 range:NSMakeRange(0, [httpLine length])];

// check that our NSRange object is not equal to range of NSNotFound
if (!NSEqualRanges(rangeOfFirstMatch, NSMakeRange(NSNotFound, 0))) {
    // Since we know that we found a match, get the substring from the parent string by using our NSRange object

    NSString *substringForFirstMatch = [httpLine substringWithRange:rangeOfFirstMatch];

    NSLog(@"Extracted URL: %@",substringForFirstMatch);
    NSLog(@"All Extracted URLs: %@",arrayOfAllMatches);

    // return all matching url strings
    return arrayOfAllMatches;
}

return NULL;

}

Вот мой вывод NSLog:

Extracted URL: http://example.com/myplayer    
All Extracted URLs: (
    "<NSExtendedRegularExpressionCheckingResult: 0x106ddb0>{728, 53}{<NSRegularExpression: 0x106bc30> http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)? 0x1}",
    "<NSExtendedRegularExpressionCheckingResult: 0x106ddf0>{956, 66}{<NSRegularExpression: 0x106bc30> http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)? 0x1}",
    "<NSExtendedRegularExpressionCheckingResult: 0x106de30>{1046, 63}{<NSRegularExpression: 0x106bc30> http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)? 0x1}",
    "<NSExtendedRegularExpressionCheckingResult: 0x106de70>{1129, 67}{<NSRegularExpression: 0x106bc30> http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)? 0x1}"
)

Ответы [ 5 ]

21 голосов
/ 06 марта 2012

Метод matchesInString:options:range: возвращает массив NSTextCheckingResult объектов.Вы можете использовать быстрое перечисление для перебора массива, извлечения подстроки каждого совпадения из исходной строки и добавления подстроки в новый массив.

NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?" options:NSRegularExpressionCaseInsensitive error:&error];

NSArray *arrayOfAllMatches = [regex matchesInString:httpLine options:0 range:NSMakeRange(0, [httpLine length])];

NSMutableArray *arrayOfURLs = [[NSMutableArray alloc] init];

for (NSTextCheckingResult *match in arrayOfAllMatches) {    
    NSString* substringForMatch = [httpLine substringWithRange:match.range];
    NSLog(@"Extracted URL: %@",substringForMatch);

    [arrayOfURLs addObject:substringForMatch];
}

// return non-mutable version of the array
return [NSArray arrayWithArray:arrayOfURLs];
14 голосов
/ 02 мая 2013

Попробуйте NSDataDetector

NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil];
NSArray *matches = [linkDetector matchesInString:text options:0 range:NSMakeRange(0, [text length])];
8 голосов
/ 07 апреля 2015

С NSDataDetector с использованием Swift:

let types: NSTextCheckingType = .Link
var error : NSError?

let detector = NSDataDetector(types: types.rawValue, error: &error)        
var matches = detector!.matchesInString(text, options: nil, range: NSMakeRange(0, count(text)))

for match in matches {
   println(match.URL!)
}

С использованием Swift 2.0:

let text = "http://www.google.com. http://www.bla.com"
let types: NSTextCheckingType = .Link

let detector = try? NSDataDetector(types: types.rawValue)

guard let detect = detector else {
   return
}

let matches = detect.matchesInString(text, options: .ReportCompletion, range: NSMakeRange(0, text.characters.count))

for match in matches {
   print(match.URL!)
}

Использование Swift 3.0

let text = "http://www.google.com. http://www.bla.com"
let types: NSTextCheckingResult.CheckingType = .link

let detector = try? NSDataDetector(types: types.rawValue)

let matches = detector?.matches(in: text, options: .reportCompletion, range: NSMakeRange(0, text.characters.count))

for match in matches! {
   print(match.url!)
}
5 голосов
/ 03 декабря 2012

чтобы получить все ссылки из заданной строки

NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:@"(?i)\\b((?:[a-z][\\w-]+:(?:/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’]))" options:NSRegularExpressionCaseInsensitive error:NULL];
NSString *someString = @"www.facebook.com/link/index.php This is a sample www.google.com of a http://abc.com/efg.php?EFAei687e3EsA sentence with a URL within it.";

NSArray *matches = [expression matchesInString:someString options:NSMatchingCompleted range:NSMakeRange(0, someString.length)];
for (NSTextCheckingResult *result in matches) {
        NSString *url = [someString substringWithRange:result.range];
        NSLog(@"found url:%@", url);
}
2 голосов
/ 05 февраля 2013

Меня настолько тошнило от сложности этой простой операции («сопоставить ВСЕ подстроки»), что я сделал небольшую библиотеку, которую я скромно вызываю Unsuck , которая добавляет здравомыслие к NSRegularExpression в форма from и allMatches методов. Вот как бы вы их использовали:

NSRegularExpression *re = [NSRegularExpression from: @"(?i)\\b(https?://.*)\\b"]; // or whatever your favorite regex is; Hossam's seems pretty good
NSArray *matches = [re allMatches:httpLine];

Пожалуйста проверьте исходный код unsuck на github и расскажите мне все, что я сделал не так: -)

Обратите внимание, что (?i) делает его нечувствительным к регистру, поэтому вам не нужно указывать NSRegularExpressionCaseInsensitive.

...