Como fazer feeds de sites dos outros com PHP

De vez em quando recebo emails de pessoas querendo aprender como fazer pra criar feeds de sites dos outros, assim como eu já fiz de diversos sites que, pelo menos na época, ainda não disponibilizavam nenhum tipo de feed.

A dificuldade para se criar feeds de sites dos outros é inversamente proporcional à qualidade do código (X)HTML do site em questão. O problema é que, em geral, os sites que têm um código mais arrumadinho, com algum cuidado tanto com sintaxe quanto com semântica, muito provavelmente já disponibilizam seus próprios feeds.

Portanto, o que nos sobra são aqueles sites que têm algum conteúdo que nos interessa, mas cujo desenvolvedor, além de não saber ainda o que é um feed, também não faz idéia de como escrever decentemente um documento HTML.

O trabalho consiste basicamente de cinco passos:

  1. Pegar o código do site (via HTTP)
  2. Analizar o código e identificar onde está o conteúdo que nos interessa:
    • Título
    • Data de publicação
    • Autor
    • Link
    • Sumário e/ou conteúdo
  3. Criar expressões regulares para isolar cada um desses dados
  4. Preparar os dados para inserção no feed
  5. Iterar pelos dados e criar, enfim, o código do feed

Com certeza, os passos mais complicados são o passo 2 e o passo 3. Para eles não há receita de bolo. Cada caso é um caso e alguns casos podem te tirar algumas noites de sono pra resolver.

Vamos passo a passo. Vamos usar um site fictício, sitesemfeed.com:

Comece seu código colocando em uma variável a URL onde se encontra o conteúdo que você deseja transformar em feed:

<?php
$url = "http://semfeed.com/arquivo.html";

Pegar o código do site via HTTP

Esse passo é simples. Há duas maneiras. Uma usando file() (ou file_get_contents()), que só vai funcionar caso seu provedor de hospedagem tenha allow_url_fopen habilitado o que não é muito seguro e a maioria das hospedagens, incluindo a dreamhost, deixam desabilitado, e a outra usando CURL.

Para a primeira opção o código é simples:

Se a sua versão do PHP for menor que 4.3.0, use o seguinte:

$content = file($url);
$content = implode('', $content);

Caso contrário:

$content = file_get_contents($url);

Nesse ponto, o código HTML inteiro retornado pela URL do nosso site está na variável $content.

Pode ser interessante, em alguns casos, remover as quebras de linha do código. Faça assim:

$content = str_replace("\r", "", $content);
$content = str_replace("\n", "", $content);

Se você precisar usar o CURL, aqui está uma funçãozinha simples, tirada do próprio site do PHP:

function open_url($url){
$curl = curl_init();
curl_setopt ($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$content = curl_exec ($curl);
curl_close ($curl);
return $content;
}

Use assim:

$content = open_url($url);

Em qualquer um dos casos, a não ser que o site em questão já esteja em UTF-8, faça:

$content = utf8_encode($content); //se o site for em ISO-8859-1
$content = iconv('windows-1252', 'UTF-8', $content); //caso seja windows-1252

Tente sempre com o primeiro exemplo. Se der algum problema, tente o segundo. Sites em windows-1252 frequentemente aparecem como ISO-8859-1 para os browsers. Mais sobre encodings e a diferença entre ISO-8859-1 e windows-1252.

Analizar o código e identificar onde está o conteúdo que nos interessa

Essa parte vai ser tão difícil quanto mais bizarro for o código do site. Para simplificar o artigo, vamos imaginar que o site tenha apenas título, data, link e um sumário.

Este é o código que marca os títulos:

<tr><td><font face="Verdana" size="3" color="#000FF"><a HREF="001.html">Aqui está o título!</a></td></tr>

Claro, agradeça aos céus se o código que você for trabalhar for tão simples assim, com tags de fechamento, por exemplo. Frequentemente encontramos coisas muito mais bizarras por aí.

Enfim, o que podemos usar como informação única para identificar o título? Talvez a cor da fonte, talvez o tamanho. Você vai precisar olhar o restante do código pra saber o que tem de único nessa marcação. Claro, uma classe já ajudaria muito, mas não conte com isso.

Vamos usar a cor e o tamanho da fonte como nossos "flags" para os títulos.

De quebra temos o link nessa mesma linha. Sorte nossa. :)

Vamos ao código das datas:

<td><font size="1">11 de novembro de 2006</font></td>

Aqui teríamos um problema. Várias outras informações no site estão em um FONT com tamanho 1 dentro de um TD. Vamos tentar usar o formato da data para identificar as datas para o feed.

Agora o código dos sumários:

<table border=0 cellspacing="0"><tr><font size="2" color="#000000">Este é o sumário do <a href="teste.html">texto</a><br><b>cheio de marcação estranha <i></b>etc e tal<br><br>E por aí vai...</font><td></td></tr></table>

Mais uma vez, temos em diversos outros pontos do site, a mesma fonte, dentro de um TD, etc. Mas, por sorte, podemos usar a tabela com um único TR e um único TD como identificador para nossos sumários.

Claro que, como já disse, não é fácil reproduzir as bizarrices que costumam fazer por aí. Portanto, pode ser que você encontre casos muito mais complicados, quase impossíveis. Mas, nesses casos, seu sucesso vai depender de sua perspicácia. Novamente, não tem receita de bolo…

Criar expressões regulares para isolar cada um desses dados

Para os títulos e links:

preg_match_all("/<tr><td><font face=\".+\" size=\"3\" color=\"#000FF\"><a [Hh][Rr][Ee][Ff]=\"([^\"]+)\">(.+)<\/a><\/td><\/tr>/", $content, $tit_links);

A variável $tit_links é um array contendo os resultados da busca usando a expressão regular. O índice 0 contém a string completa, 1 contém o conteúdo do primeiro parêntese, o 2 o do segundo parêntese e por aí vai.

Não vou explicar aqui como funcionam expressões regulares. Se você não conhece o assunto, vale muito a pena aprender. Há um guia excelente na web e um livro, escritos pelo mesmo autor, Aurélio Marinho Jargas.

Vamos à ER para as datas:

preg_match_all("/<td><font size=\"[0-9]\">([0-9][0-9]? de [A-Za-z]+ de [0-9][0-9][0-9][0-9])<\/font><\/td>/", $content, $dates);

Há meios de se usar expressões mais complexas e menos extensas para este mesmo caso, mas procurei simplificar para tentar facilitar o entendimento.

Agora os sumários:

preg_match_all("/<table border=\"?0\"? cellspacing=\"[0-9]\"><tr><td><font size=\"[0-9]\" color=\"#[0-9]+\">(.+)</font><td><\/td><\/tr><\/table>/", $content, $summaries);

Estou levando em conta que podem, no futuro, resolver mudar o tamanho da fonte, ou colocar aspas nos atributos que não as têm.

Perceba que estou usando um caso fictício, não testado, apenas para exemplificar. Se você não analizar por si mesmo o site e não entender como as expressões regulares funcionam, é melhor nem tentar fazer um feed.

Mas, eu não poderia usar um parser HTML? Talvez sim. Eu já fiz alguns testes e achei mais fácil usar expressões regulares. Se você teve alguma experiência boa usando um parser HTML em PHP, conte pra gente.

Se o cara que fez o site mudar o código, meu feed já era? Yep. Esse é um grande problema de feeds feitos dessa forma. Se o cidadão mudar o código seu feed pára de funcionar. Simples assim.

E quanto ao copyright do site do camarada? Bem, tome cuidado com isso. É melhor consultar o dono do site antes, ou então assumir os riscos, se você tiver cara pra isso…

Criando o feed

Nesse ponto vamos iterar pelos itens coletados com as expressões regulares e criar o código do feed. Vou usar o formato RSS 2.0, que é mais popular.

O passo "preparar os dados para inserção no feed" vai ser feito dentro da iteração.

<?php
header("Content-type: application/xml; charset=utf-8"); //Sem isso, o arquivo será enviado como HTML
echo '<?xml version="1.0" encoding="utf-8"?>' . "\n";
?>
<rss version="2.0">
<channel>
<title>Site Sem Feed</title>
<link><?php echo $url ?></link>
?>
for ($i=0; $i<sizeof($tit_links); $i++): //considerando que todos os arrays tem o mesmo número de índices, não importa muito o tamanho de qual você pega aqui
$title = $tit_links[2][$i];
$link = $tit_links[1][$i];
$tz_offset = -3;
$date = date("D, d M Y H:i:s \G\M\T", strtotime($dates[1][$i]) + ($tz_offset * 3600)); //Isso aqui não vai funcionar, na verdade. Você vai ter que queimar a mufa pra transformar aquela data do exemplo em algo usável. Tô sem saco pra isso agora...
$summary = $summaries[1][$i];
$summary = strip_tags($summary, '<a> <br>
<p>');
?>
<item>
<title><?php echo $title ?></title>
<link><?php echo $link ?></link>
<pubDate><?php echo $date ?></pubDate>
<description><![CDATA[ <?php echo $summary ?> ]]></description>
</item>
<?phpphp endfor; ?>
</channel>
</rss>

E assim está feito nosso feed.

Antes de ter sucesso, você vai provavelmente ter que fazer diversos testes, arrancar alguns cabelos, xingar a mãe do cara que fez aquele site tão bizarro e tudo mais. Mas, quem quis fazer o feed foi você, então agüenta, malandro.

Leia também:

34 Comentários sobre “Como fazer feeds de sites dos outros com PHP”

Faça um comentário

#1 | Tomás

Uma sugestão seria usar as funções DOM do PHP.

Por que as vezes fica difícil isolar o conteúdo usando apenas expressões regulares, aconteceu comigo qndo fui tentar fazer isso para criar feeds para fotologs hospedados no flogao.com.br.


#2 | Fabrício

Por acaso vc não tem pronto o feed do malvados não? eu não sei ER ainda =~~~/


Pra quem não manja de ER, existe o feed43.com (trocadilho com ‘feed for free’), que permite criar feeds escrevendo arremedos de ER :-)

Ah sim, eu leio feeds no Bloglines, que costuma ser “esperto” na hora de encontrar feeds… Se você pede pra assinar o feed de malvados.com.br, ele encontra :-) [eu fiz isso, e se não me engano o que ele achou era justamente um feed43 feito por outra pessoa]

Já fiz um desses feeds uma vez, não que eu não manje de ER (trabalho com isso o tempo todo), mas mais por preguiça e por ficar fácil deixar público.


Como faço para fazer feeds do meu site que está em (X)HTML sem usar PHP?


#5 | Leandro

Boa pedida Lukas, um tutorial de como fazer feeds no teu site sem ser em PHP.

Parabéns pelo artigo Bruno.


#6 | zeh

Valew Bruno com esse texto eu criei coragem e fiz o meu primeiro feed…pensei que era mais dificiul…
valeww


E por que não compartilha com a gente a sua criação, Zeh?


O elcio do fechaTag fez, a muito tempo, um post sobre RSSficar sites so que em ASP, vale a pesquisada.


#9 | higor

quero saber como fazer magica


#10 | Lorn

Fala Bruno :)
Legal esse esquema de fazer feed com php, mas como sou um fanático por perl :) indico ele pra fazer feeds de sites complicado, infelizmente não é todo mundo que sabe, mais tem um modulo HTML::TreeBuilder, que faz todo o trabalho sujo de regexp pra você, você só passa as tags que quer.
Até mais.

PS: Com php é mais “facil’ porque todo mundo conhece php :)


Fiz o feed do O Velho!

Muito obrigado, Bruno! Sua metodologia é igual a um mapa de tesouro cara: é só seguir as indicações que a gente chega no X da questão.

O “O Velho” é um site de notícias variadas sobre tecnologia e “cybercultura”. Eu vejo ele todos os dias e agora vou poder acompanhar ele através do feed. http://www.ovelho.com

Infelizmente não tenho um site de imediato em que eu possa postá-lo. Vou tentar conseguir um e se conseguir eu coloco o link aqui.

Arquivo com o código: http://gevaspm.googlepages.com/ovelho.zip

Screenshots
http://gevaspm.googlepages.com/feed_ovelho.jpg
http://gevaspm.googlepages.com/feed_ovelho_2.jpg


Segue um screenshot do Sage (sage.mozdev.org) lendo o feed do O Velho:
http://gevaspm.googlepages.com/sage_ovelho.jpg


#13 | Pedro Paulo

Aleluia!!! Eu consegui! Passei 12 horas no computador, mas consegui.

Para os que gostam do Jacaré Banguela tenho uma boa notícia :)

O link para o feed (Completo) deles é:

http://feeds.feedburner.com/JacareBanguela

Espero que gostem.
Para os curiosos o link para o código fonte é:

http://feedsbypedro.googlepages.com/jacarebanguela.txt


Ficou muito bom Pedro Paulo. Já assinei.

Só uma pergunta: foi realmente necessário tratar os acentos daquela maneira?


Vi o código do Jacaré Banguela e vi que realmente foi necessário tratar os acentos e espaços.


#16 | Pedro Paulo

Não mais. :D O código foi atualizado e agora esse truque não é mais necessário.

Ainda acho que está meio sujo, mas dá pro gasto :)


#17 | Felipe

É minha impressão ou o Bruno deixou algumas pedras no meio do caminho para evitar que Script Kiddies se aproveitem de seu código? :twisted:


queria criar um feed pro meu site mas não sei como fazx pois não manjo nada alguem poderia me ajudar…

o site é http://www.radiodjn.com

quem puder ajudar o meu email dj.naninho@radiodjn.com

abracos


Estou tentando criar um feed de um site de parceiro alguns imóveis para o meu site. Só que quando faço a divulgação do link da pagina no XML o arquivo retorna um erro igual a este:
“A página XML não pode ser exibida
Não é possível exibir a entrada XML usando a folha de estilos XSL. Corrija o erro e clique no botão Atualizar ou tente novamente mais tarde.

Um ponto-e-vírgula era esperado. Erro ao processar o recurso ‘http://www.uberimoveis.com.br/feed2.php’. Linha 5, posição 61

http://www.ivannegocios.com.br/imoveis.aspx?fin=1&tipo=2&bairro=&vlr1=100&vlr2=999999.99


Ah esqueci de deixar meu email: randermendonca@gmail.com


Tentei a rotina em php mas só funciona para sites com o código muito organizado.


Olá consegui achar o problema, realmente era o operador “&” que estava dando problema. O XML não aceita os operadores “&” e “>”. Para que eles possam ser processados no XML devem estar dentro de “” para verificar mais a respeito visite http://www.w3schools.com/xml/xml_cdata.asp .
Valeu


então, gostari de criar um feed, e depois participar com os amigos que for conhecendo, nesse universo.


eu quero fazer um feed paea exibir no meu orkut


ganha o jogo de grates


#26 | luta

esse sim é aluta livre com sertesa estre nesse site aii hahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahaha


#27 | Danilo Alex

Cara,
Muito muito obrigado pela dica! Estava tentando usar RSS no site mas acontece q o servidor não permiti a fopen e aí usei a sua dica (function open_url) e funcionou perfeito!
Valeu cara pela contribuição!
Parabéns


[...] do blog, agora se você é um webdesigner e deseja criar um feed para o seu site, indico a leitura deste artigo de Bruno Torres onde ele ensina passo a passo como fazer isso, mas atenção: O processo de [...]


Leech agora virou feed? rsrs


Quem poderia criar um feed do site http://www.webluxo.com.br??

ficaria muito grato..

Obrigado.


que isso é muito interesante na vida das pessoas para um modo de sobreviver fazendo feeds.abraços


#32 | Andre

Olha tenho um XML com informações dinamicas, tive uma idéia retirar informações interessantes dele e criar um um arquivo RSS apartir do XML, só que as strings quando são impressas estão indo sem valor…parece macumba, só consigo imprimir a carcaça os valores estão indo em branco.


[...] quase lá: http://s2n.com.br/rss/deathsign.php, usando os conhecimentos do bruno torres e seu post: Como fazer feeds de sites dos outros com PHP desenvolvi o RSS para o dh, que é um dos melhores hq`s que conheci recentemente que veio via [...]


Opa fiz um mini tuto de como analizar o blog, site etc.
Sei q não tem muito aver com feed mais é bom dar uma olhada quem quer UPAR seu site.
É tudo pela internet (não prescisa instalar nada).

Bom post. Até mais !

http://www.gasparimsat.com/index.php/28/04/2009/analizar-a-velocidade-do-seu-site/


«

»

Deixe seu comentário


Veja as estatísticas