regex extratora de URLs
Acabei precisando de um filtro que separe (especificamente, remova) as URLs de um arquivo de texto qualquer. Imaginei que, sendo esta uma tarefa bastante recorrente na programação para Web (por exemplo, para linkar automaticamente todas as URLs do texto), existiria uma solução comum e padronizada em forma de regular expression.
Ledo engano! As implementações que encontrei eram ou ridículas de simples (e não pegavam nem metade das minhas URLs), ou então absurdamente complexas (e incompatíveis com o meu caso e/ou lentas). OK, o jeito, para PHP, foi esse:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | if ($fh = @fopen($argv[1], 'r')) { while (!feof($fh)) { preg_match_all( '% ( (ftp|https?):\/\/ ([a-z0-9\-_]+(:[^@]+)?\@)? ( ([a-z0-9\.\-]+)\.([a-z\.]{2,6}) | ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}) ) (:[0-9]{2,5})? ( [a-z0-9\.\-_/\+\%&;\:,\=\!@\(\)\[\]~\'\"]* [a-z0-9\.\-_/\+\%&;\:,\=\!@\(\)\[\]~]+ ) (\?[a-z0-9\.\-_/\+\%&;\:,\=\!@\(\)\[\]~]*)? (\#[a-z0-9\.\-_/\+\%&;\:,\=\!@\(\)\[\]~]*)? ) %ix', fgets($fh), $urls, PREG_PATTERN_ORDER ); foreach ($urls[0] as $url) echo "$url\n"; } fclose($fh); } |
O que isso faz é pegar qualquer um arquivo de texto passado como parâmetro, processar ele, extrair as URLs e imprimi-las. E qual o diferencial?
- Testei com umas 4 mil URLs do meu del.icio.us e mais 12 mil do meu histórico do Firefox, e funcionou satisfatoriamente;
- Testei com o dump do Wikipédia, e a velocidade de processamento foi de 3.85 MB/s;
- Do jeito que está, a regex não usa nenhum dialeto estapafúrdio, e é perfeitamente compatível com PHP e Perl. Mas portar para, digamos, JavaScript deve ser dois palitos (juntar tudo numa linha só, presumo).
É isso aí. Se lhe serviu para alguma coisa, poste nos comments