Olá pessoal. Esse é meu primeiro artigo aqui no iMasters e espero que vocês gostem.
Conhecimentos necessários.
Para o melhor aproveito deste artigo é bom que você tenha familiaridade com alguma linguagem de programação server-side e básicos conhecimentos em Ajax e W3C DOM.
Vou explicar como fazer um serviço de busca no YAHOO! usando Ajax e PHP.
Para entender melhor o que seria um Web Service clique aqui.
As técnicas mais conhecidas são SOAP (Simple Object Access Protocol) e a WSDL (Web Services Description Language) mas a técnica que o YAHOO! escolheu é a REST.
A REST é o protocolo publico que o YAHOO! disponibiliza seus serviços. Eles a escolheram pois são fáceis de entender e apreciam sua acessibilidade à maioria das linguagens de programação modernas.
Por que usar a REST (Representational State Transfer)?
Com ela podemos solicitar dados através de uma URL (via GET) de um serviço e adicionamos somente parâmetros para a busca. É a forma que usamos hoje para muitos serviços. Um exemplo seria http://www.minhapagina.com.br?categoria=futebol.
Técnicas como a SOAP é necessário o envio de uma XML via POST, isso pode ser mais propenso a erros, pois podemos esquecer uma aspa e outra ali.
Sobre o serviço do YAHOO!
Além de você poder buscar em toda a internet, você também pode fazer a busca somente em um site específico. Desta forma, você aproveita os índices os YAHOO! para criar uma busca interna em seu site, sem se preocupar em cadastrar em um banco de dados.
Para maiores detalhes sobre parâmetros que podemos passar, acesse: http://developer.yahoo.com/search/web/V1/webSearch.html
XMLHttpRequest é o método perfeito para o acesso?
Considerando que o retorno do conteúdo do YAHOO! vem através de uma XML e podemos usar os métodos W3C DOM para manipular os resultado, ele é um ótimo método. Porém esse método só tem acesso a recursos dentro do mesmo domínio que o documento que o conteúdo foi gerado.
O que podemos fazer é criar uma gateway (nada mais é que uma porta de saída). O gateway aceitará solicitações do objeto XMLHttpRequest e a encaminhará para o YAHOO!. Quando o YAHOO! responder com os resultados da busca o gateway simplesmente roteará para o navegador. A vantagem de usamos um gateway é que posteriormente podemos estender esse serviço com outro buscadores.
Criando a Gateway
Para esse artigo usaremos PHP como linguagem server-side, mas você pode escolher a linguagem que esteja mais familiarizado. A gateway só vai ler o conteúdo de uma URL, já com os parâmetros de busca concatenados na string.
<?php
//informa ao navegador que o retorno do documento é uma xml
header ("content-type: text/xml");
//recebe os parametros para gerar a query
$query = (string) urlencode ( $_REQUEST['query'] );
$resultados = (int) $_REQUEST['resultados'];
$regiao = (string) $_REQUEST['regiao'] != "internet" ? $_REQUEST['regiao'] : NULL;
$site = (string) $_REQUEST['site'];
//Busca o resultado da busca
$handle = fopen ("http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=seu_app_id&type=all&query=".$query."&results=".$resultados."®ion=".$regiao."&site=". $site,'r');
//enquanto houver resutados ele exibe na tela para o ajax
while (!feof ($handle)) {
$buffer = fgets( $handle , 4096 );
echo $buffer;
}
//fecha a URL solicitada
fclose ( $handle );
?>
Creio que os comentários já são auto-explicativos.
Criando o JavaScript
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Minha busca no YAHOO!</title>
<script type="text/javascript">
var xmlHttp;
//CRIA UMA CONEXÃO XMLHttpRequest
function ajaxInit () {
try {
xmlHttp = new XMLHttpRequest();
}
catch (ee){
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (E) {
alert("Seu browser não está comJavaScript ativado!");
}
}
}
}
function buscar (){
//exibe um status da busca para o usuario final
loading();
//URL que iremos utilizar com gateway
var url = "http://localhost/imasters/yahoo_gateway.php?" + generateQueryString();
//instacia o objeto XMLHttpRequest
ajaxInit();
//chama a função que controla os estados da requisição
xmlHttp.onreadystatechange = mudarEstado;
//abre a conexão
xmlHttp.open ( "GET" , url , true );
xmlHttp.send(null);
}
function loading () {
//somente adiciona um texto carregando para o usuario saber quer algo está sendo feito
var resultados = document.getElementById('resultados').innerHTML = "Carregando...";
}
A primeira coisa a fazer é criar o objeto XMLHttpRequest. Creio que você já esteja acostumado a manipular esse objeto.
O próximo passo é criar a função que será chamada ao executar o evento da busca.
Nesta função, também não temos tantas novidades. Somente atribuímos a função mudarEstado para cada alteração onreadystatechange.
/**
* Busca os valores e os concatena em uma string para enviar ao nosso gateway
*/
function generateQueryString() {
//pega os valores da busca do usuario
var query = document.getElementById('query').value;
var quantidade = document.getElementById('quantidade').value;
var site = document.getElementById('local').value;
var regiao = document.getElementById('regiao').value;
var ts = new Date().getTime();
//A hora ao final da query string é somente para evitarmos cache
return "query=" + query + "&resultados=" + quantidade + "&site=" + site + "®iao=" + regiao + "&ts=" + ts;
}
function mudarEstado(){
if ( xmlHttp.readyState == 4 ){
if ( xmlHttp.status == 200 ) {
parseTodosResultados();
}
else {
alert ("Ocorreu um erro ao acessar o YAHOO!");
}
}
}
Na função mudarEstado verificamos se o documento foi recebido com sucesso. Caso não tenha problemas, chamamos a função parseTodosResultados.
/**
* Vamos fazer o parse de toda XML aqui
* Ela navega em cada nó RESULT e passa para a parseResultado para exibirmos para o usuario final
*/
function parseTodosResultados (){
//apaga se houver resultados anteriores!
limpar();
//pega o nó com os resultados "Result"
var resultados = xmlHttp.responseXML.getElementsByTagName("Result");
//Caso não encontre resultados
if ( resultados.length == 0 ){
document.getElementById('resultados').innerHTML = "não há resultados para a busca";
return;
}
//para saber o total de resultados
headerSets();
var resultado = null;
//navega entre os resultados
for (var i = 0 ; i < resultados.length; i++){
resultado = resultados[i];
parseResultado( resultado );
}
}
/**
* Função para uma futura paginação de resultados.
*/
function headerSets(){
//antes/após lermos as tags result podemos querer gerar uma páginação dos resultados
//para isso o YAHOO! disponibiliza como a primeira tag ResultSet onde eles exibem o total de resultados disponiveis
var resultSet = xmlHttp.responseXML.getElementsByTagName ("ResultSet");
var totalResultados = resultSet[0].attributes['totalResultsAvailable'].nodeValue;
//para a criação de páginação de resultados deixarei como exercicio.
}
Na função parseTodosResultados() atribuímos a variável “resultados” todos os nós <Result>. Caso não tenha nenhum nó, exibimos para o usuário que não há resultados.
Do contrário vamos navegar em cada nó <Result> e passaremos os resultados para a função parseResultado().
/**
* Esssa função recebe um nó result e irá extrair seus valores
* Ela utiliza métodos W3C DOM para gerar código XHTML
* OBS.: criei uma função chamada getElementoTexto ela extrai o texto do nó informado.
*/
function parseResultado ( resultado ){
//cria uma div onde o resultado ficara dentro
var div = document.createElement("div");
//cria um elemento h3 para os titulos
var titulo = document.createElement("h3");
//extrai do nó "Title" seu texto e adiciona o texto para o titulo
titulo.appendChild( document.createTextNode( getElementoTexto( resultado , "Title" ) ) );
//adiciona o titulo para a div
div.appendChild ( titulo );
//cria um texto e extrai o texto do no "Sumary"
var descricao = document.createTextNode( getElementoTexto( resultado , "Summary" ) );
//adiciona para a div o texto
div.appendChild( descricao );
//cria um elemento <br /> para quebrar a linha
div.appendChild( document.createElement("br") );
//criamos um elemento para um link
var tagLink = document.createElement( "a" );
//adiciona o atrubuto href da tag e extrai o link absoluto até a página da busca
tagLink.setAttribute ("href" , getElementoTexto( resultado , "ClickUrl" ));
//para abrir em uma nova página
tagLink.setAttribute ("target" , "_blank" );
//o texto do link que vai ser exibido para o usuario final
txtLink = document.createTextNode( getElementoTexto ( resultado , "DisplayUrl") );
//adiconamos o texto do link para a tag A
tagLink.appendChild ( txtLink );
//coloca o link dentro da div
div.appendChild( tagLink );
//um linha vertical
div.appendChild( document.createElement("hr") );
//colocamos toda a div no local dos resultados
document.getElementById('resultados').appendChild( div );
}
A função parseResultado nada mais faz que criar o XHTML que iremos exibir os resultados. Nela utilizamos o W3C DOM para gerarmos a página de resultados.
O primeiro passo da função é criar uma <div> que irá abrigar todos os dados da busca (titulo, descrição, link, etc..).
Depois criamos um <h3> que nos servirá como titulo da cada resultado.
Então nos adicionamos ao titulo o texto contido na tag <Title> e encontramos outra função muito importante a getElementoTexto.
/**
* Essa função extrai o texto dentro de uma tag especifica
* Ela recebe como parâmetro todo o nó result e ainda o elemento que desejamos extrair
*/
function getElementoTexto ( parentNode , atributo ) {
//no nó result ele ira busca todas as tag com o atributo q desejamos ("title","sumary")
var childTag = parentNode.getElementsByTagName( atributo );
//caso tenha algum valor
if (childTag[0].firstChild != null)
//do primeiro nó encontrado (firstChild) ele retorna o conteudo dentro da tag (nodeValue)
return childTag[0].firstChild.nodeValue;
}
function limpar(){
//pega os resultados antigos
var resultados = document.getElementById('resultados');
while (resultados.childNodes.length > 0){
//remove o primeiro no dos resultados antigos
resultados.removeChild(resultados.childNodes[0]);
}
}
</script>
<style type="text/css">
#resultados {
border: 1px solid #ccc;
background-color: #eee;
font-family: Arial, Helvetica, sans-serif;
}
#resultados h3 {
color: #000066;
}
</style>
</body>
</html>
Considerações finais
Como vocês viram, é bem simples utilizar a API do YAHOO! Para realizar consultas na internet ou mesmo no seu site. Confira na parte de developers do YAHOO! outros parâmetros que podemos utilizar para filtrar melhor ainda a busca.
Outra coisa importante, que vale a pena mencionar, é que na primeira TAG de retorno do YAHOO!, ele nos informa a quantidade de resultados. A função headerSets pega esses valores. Eu só não implementei a parte de criar a paginação de resultados. Deixo isso como um tarefa de casa. Tente fazê-la utilizando métodos W3C DOM.
Estes são os arquivos do artigo Download
Bom pessoal, é isso! Até a próxima!