Criação de robô HTTP em Java

32 respostas
A

Olá,

Estou querendo criar um robô HTTP em Java, para aprendizado, apenas. Bem, a única coisa que este robô deve fazer é solicitar o usuário e a senha do usuário aqui do GUJ, e após isso retornar sua classificação (What the classpath?, Virtual Machine Man, GUJ Ranger, e etc). Bem, sei que posso fazer isso através de sockets, no entanto, não domino-o por completo. Tudo que sei fazer com sockets em Java é trocar mensagens entre cliente e servidor. Enfim, alguém poderia me apontar o caminho das pedras, através de sockets? Ou, se houver, sugerir uma API para facilitar meu trabalho?

Aguardo resposta,
André Rosa.

32 Respostas

J

Tbm quero saber se alguém sugerir algo.

I

Muito boa a sua iniciativa de aprendizado, soh tenho uma dúvida:
quem vai passar a senha aqui do guj pra vc?
nao entendi muito bem?
vai manipular a senha do usario aqui do guj?
acho estranho hem…
mas eu pq acho que nao entendi a sua idea…

R

a ideia é o seguinte:
basicamente vc vai utilizar a Runtime para poder executar os programas tipo: mandar abrir o browser.

depois vc vai utilizar a classe robot , mas antes vc precisa ler a pagina para poder colocar os comandos nos lugares certos.

bom, basicamente isto.

fica a dica…

A

ivansalvadori:
Muito boa a sua iniciativa de aprendizado, soh tenho uma dúvida:
quem vai passar a senha aqui do guj pra vc?
nao entendi muito bem?
vai manipular a senha do usario aqui do guj?
acho estranho hem…
mas eu pq acho que nao entendi a sua idea…

Não é para me passar a senha. Talvez nem precise. A senha seria só para poder chegar ao perfil do usuário em questão, mas talvez só seja necessário informar a id do perfil. Eu encontrei um exemplo de robô HTTP, só que em C.

Um abraço,
Aguardo mais respostas.

A

rjbcordeiro:
a ideia é o seguinte:
basicamente vc vai utilizar a Runtime para poder executar os programas tipo: mandar abrir o browser.

depois vc vai utilizar a classe robot , mas antes vc precisa ler a pagina para poder colocar os comandos nos lugares certos.

bom, basicamente isto.

fica a dica…

Legal, mas teria de ser algo independente de browser. Como neste exemplo:

http://www.vivaolinux.com.br/script/Robo-HTTP-usando-socket-e-codigo-multiplataforma

M

André,

Precisei fazer algo parecido uma vez.

Utilizei sockets e o exemplo que utilizei para resolver esse requisito foi esse: http://www.java2s.com/Code/Java/Network-Protocol/SendingaPOSTRequestUsingaSocket.htm

Esse exemplo mostra como executar o post em uma página e pega o retorno após o post.

Att.

A

molmedo:
André,

Precisei fazer algo parecido uma vez.

Utilizei sockets e o exemplo que utilizei para resolver esse requisito foi esse: http://www.java2s.com/Code/Java/Network-Protocol/SendingaPOSTRequestUsingaSocket.htm

Esse exemplo mostra como executar o post em uma página e pega o retorno após o post.

Att.

Muito obrigado, molmedo. Com toda certeza será de extrema utilidade.

R

Andre Rosa:
molmedo:
André,

Precisei fazer algo parecido uma vez.

Utilizei sockets e o exemplo que utilizei para resolver esse requisito foi esse: http://www.java2s.com/Code/Java/Network-Protocol/SendingaPOSTRequestUsingaSocket.htm

Esse exemplo mostra como executar o post em uma página e pega o retorno após o post.

Att.

Muito obrigado, molmedo. Com toda certeza será de extrema utilidade.

sim com isto vc pode pegar a página, mas como vai executar um evento?

tipo o robot(no caso do awt) ele cria eventos como se fosse um usuario de verdade, mas com sockets como vc vai dar um evento de click em um botão?(por exemplo)

----- OPS FOI MAUS , ENTENDI AGORA…

M

rjbcordeiro:
Andre Rosa:
molmedo:
André,

Precisei fazer algo parecido uma vez.

Utilizei sockets e o exemplo que utilizei para resolver esse requisito foi esse: http://www.java2s.com/Code/Java/Network-Protocol/SendingaPOSTRequestUsingaSocket.htm

Esse exemplo mostra como executar o post em uma página e pega o retorno após o post.

Att.

Muito obrigado, molmedo. Com toda certeza será de extrema utilidade.

sim com isto vc pode pegar a página, mas como vai executar um evento?

tipo o robot(no caso do awt) ele cria eventos como se fosse um usuario de verdade, mas com sockets como vc vai dar um evento de click em um botão?(por exemplo)

rjbcordeiro,

Como mencionei, para o caso específico do André, onde ele sabe que são dois campos preenchidos e quer analisar algum retorno, a partir do socket você consegue simular o POST do formulário, que é a ação de clicar no botão (por exemplo).

A

Na verdade não precisarei de usuário e senha de ninguém, precisarei apenas do id do perfil. Bem, estou fazendo da seguinte forma: o usuário entra com a id, eu formulo uma string com, o endereço completo, eu baixo o código fonte HTML da página, e vejo como posso chegar até a classificação. Basicamente é isso, não será tão difícil como imaginei.

A

Olhem só que beleza:

<span class="postdetails">
				Classificação: GUJ Ranger
			
			</span>

a classificação fica dentro de uma classe especifica, e essa classe (postdetails) só está presente neste trecho.

A

Pessoal,

para onde posso jogar o código fonte da página? Pra um arquivo de texto?

R

tu pode jogar para uma variavel String e usar expressão regular para pegar o conteudo apos o “Classificação:”

ou então tu pode utilizar o jtidy , ai tu pega do inputstream, já fiz algo parecido

com o jtidy tu trabalha com o xml do html, pode ser melhor

A

rjbcordeiro:
tu pode jogar para uma variavel String e usar expressão regular para pegar o conteudo apos o “Classificação:”

ou então tu pode utilizar o jtidy , ai tu pega do inputstream, já fiz algo parecido

com o jtidy tu trabalha com o xml do html, pode ser melhor

Acho que a expressão regular seria a melhor forma. No entanto, há um problema. O código fonte é pego em loop, percorrendo linha por linha. Como eu poderia tentar casar a linha com a expressão regular? O loop está assim:

while ((LinhaCod = in.readLine()) != null){ /* imprimir o conteúdo da string LinhaCod */ }

Obrigado.

A

Ótimo! Estou salvando tudo em arquivo. Localizei a classificação:

<img src="/images/avatar/140132c1a7044bd6f7175e6d232cf277.jpg" border="0" /><br />			<span class="postdetails">				Classifica&#65533;&#65533;o: GUJ Ranger						</span>		</td>		<td class="row1" valign="top" rowspan="3">			<table cellspacing="1" cellpadding="3" width="100%" border="0">

Alguém pode me sugerir o próximo passo agora?

Outra dúvida: estou criando o objeto de escrita desta forma:

FileWriter escreve = new FileWriter(new File ("tmp.txt"), true);

Como eu poderia deletar este arquivo, já que não há nenhum objeto do tipo File para chamar o método delete()?

Obrigado.

M

Você não poderia simplesmente analisar o arquivo html com regex?

A

Não sou bom com expressões regulares. Mas vou tentar pensar nisso até chegar em casa. Ainda estou no trabalho.

R

tu não precisa criar o arquivo não.

Trabalha direto com o stream, joga tudo em um parser da vida tipo o jtidy.

Ai tu vai manipular como um xml normal.

pega o valor do *span que tem atributo class = postdetails

tira o nome classificação e mostra a classificação.

ok :slight_smile:

R

Precisei fazer um crawler para pegar endereços de futuros clientes rsrs

Fiz usando Ruby + Mechanize ficou muito fácil (sei só o basicão de Ruby)

O caminho que achei mais fácil pra pegar a classificação (usando usuario e senha):

  1. Autentica na página
  2. Vai nas minhas mensagens
  3. Pega última mensagem
  4. Procura na página o usuario para pegar a classificação

Informando o numero de perfil fica mais facil assim dá para fazer em umas 10 linhas eu acho :stuck_out_tongue:

  1. Acessa a página http://www.guj.com.br/user/profile/" + numeroPerfil + “.java”
  2. Pega o HTML e vai até o lugar onde está a classificação

Nesse segundo caso daria para usar somente Ruby + HPricot

http://www.lednerd.com/2007/04/20/extraindo-dados-com-ruby-e-hpricote/

A

rjbcordeiro:
tu não precisa criar o arquivo não.

Trabalha direto com o stream, joga tudo em um parser da vida tipo o jtidy.

Ai tu vai manipular como um xml normal.

pega o valor do *span que tem atributo class = postdetails

tira o nome classificação e mostra a classificação.

ok :)

O problema é que eu nunca usei JTidy. Você sabe onde consigo um material específico para o que quero fazer através do JTidy?

Obrigado.

A

RafaelViana:
Precisei fazer um crawler para pegar endereços de futuros clientes rsrs

Fiz usando Ruby + Mechanize ficou muito fácil (sei só o basicão de Ruby)

O caminho que achei mais fácil pra pegar a classificação (usando usuario e senha):

  1. Autentica na página
  2. Vai nas minhas mensagens
  3. Pega última mensagem
  4. Procura na página o usuario para pegar a classificação

Informando o numero de perfil fica mais facil assim dá para fazer em umas 10 linhas eu acho :stuck_out_tongue:

  1. Acessa a página http://www.guj.com.br/user/profile/" + numeroPerfil + “.java”
  2. Pega o HTML e vai até o lugar onde está a classificação

Nesse segundo caso daria para usar somente Ruby + HPricot

http://www.lednerd.com/2007/04/20/extraindo-dados-com-ruby-e-hpricote/

Sim, amigo. Estou fazendo desta segunda forma, solicitando o id do usuário. Só estou tendo dificuldades em chegar até a “classificação” no arquivo.

Obrigado!

R

Andre Rosa:
RafaelViana:
Precisei fazer um crawler para pegar endereços de futuros clientes rsrs

Fiz usando Ruby + Mechanize ficou muito fácil (sei só o basicão de Ruby)

O caminho que achei mais fácil pra pegar a classificação (usando usuario e senha):

  1. Autentica na página
  2. Vai nas minhas mensagens
  3. Pega última mensagem
  4. Procura na página o usuario para pegar a classificação

Informando o numero de perfil fica mais facil assim dá para fazer em umas 10 linhas eu acho :stuck_out_tongue:

  1. Acessa a página http://www.guj.com.br/user/profile/" + numeroPerfil + “.java”
  2. Pega o HTML e vai até o lugar onde está a classificação

Nesse segundo caso daria para usar somente Ruby + HPricot

http://www.lednerd.com/2007/04/20/extraindo-dados-com-ruby-e-hpricote/

Sim, amigo. Estou fazendo desta segunda forma, solicitando o id do usuário. Só estou tendo dificuldades em chegar até a “classificação” no arquivo.

Obrigado!

No HPricot pode se usar XPath para chegar diretamente a uma tag do HTML. Deve existir alguma biblioteca Java que faça o mesmo.

R

Não sei o porquê mas eu achei o Ruby muito fácil para fazer robôs HTTP!

Por exemplo, entre no site do HPricot:

http://hpricot.com/

Lá tem um "simulador":

1) Coloque em URL = http://www.guj.com.br/user/profile/71122.java
2) Coloque em Search = span[@class=postdetails]
3) Resultado = Classifica��o: GUJ Ranger

Agora é só fazer um split com essa string que você tem a classificação o/

Com código (não testei estou sem o Ruby instalado no PC, só para mostrar a simplicidade)
require "hpricot"
require "open-uri"

doc = Hpricot(open("http://www.guj.com.br/user/profile/71122.java"))
classificacao = doc.search("span[@class=postdetails]").inner_html

puts classificacao

com duas linhas de código você já tem a variavel classificação preenchida com: Classifica��o: GUJ Ranger

A
RafaelViana:
Não sei o porquê mas eu achei o Ruby muito fácil para fazer robôs HTTP!

Por exemplo, entre no site do HPricot:

http://hpricot.com/

Lá tem um "simulador":

1) Coloque em URL = http://www.guj.com.br/user/profile/71122.java
2) Coloque em Search = span[@class=postdetails]
3) Resultado = Classifica��o: GUJ Ranger

Agora é só fazer um split com essa string que você tem a classificação o/

Com código (não testei estou sem o Ruby instalado no PC, só para mostrar a simplicidade)
require "hpricot"
require "open-uri"

doc = Hpricot(open("http://www.guj.com.br/user/profile/71122.java"))
classificacao = doc.search("span[@class=postdetails]").inner_html

puts classificacao

com duas linhas de código você já tem a variavel classificação preenchida com: Classifica��o: GUJ Ranger

Legal, mas não achei disponível para Java. Existe, uma versão desta API para Java?

M

Olá André. Achei duas coisas interessantes. Tem uma biblioteca chamada jericho que faz html parser em Java:
http://jericho.htmlparser.net/docs/index.html

Existe também, pra minha surpresa, um componente do próprio Java chamado Swing HTML Parser:
http://java.sun.com/products/jfc/tsc/articles/bookmarks/

Espero que isso lhe seja útil.
Abraço.

A

matheuslmota:
Olá André. Achei duas coisas interessantes. Tem uma biblioteca chamada jericho que faz html parser em Java:
http://jericho.htmlparser.net/docs/index.html

Existe também, pra minha surpresa, um componente do próprio Java chamado Swing HTML Parser:
http://java.sun.com/products/jfc/tsc/articles/bookmarks/

Espero que isso lhe seja útil.
Abraço.

Obrigado, Matheus. Vou procurar me informar à respeito de suas sugestões.

R

cara fiz o que tu precisa, mas lembrando que é para fins educacionais:
qualquer dúvida tu posta ai.
Lembrando que fiz o código rapido(hoje ehehe) e se parecer inlegível… sabe como é né… é para estudos…

package javatestedesktop;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.tidy.Tidy;

/**
 *
 * @author ricardo
 */
public class TesteAutenticaçãoGuj {

    private static URLConnection con;

    public static InputStream retornainput() throws Exception{
        String param = URLEncoder.encode("username", "UTF-8") + "=" + URLEncoder.encode("login", "UTF-8");
        param += "&";
        param += URLEncoder.encode("password", "UTF-8") + "=" + URLEncoder.encode("senha", "UTF-8");
        URL url = new URL("http://www.guj.com.br/");
        con = url.openConnection();
        con.setDoOutput(true);
        OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
        osw.write(param);
        osw.flush();
        return con.getInputStream();
    }

    public static InputStream retornaInputProfiller() throws Exception{
        URL url = new URL("http://www.guj.com.br/user/profile/22019.java");
        con = url.openConnection();
        con.setDoOutput(true);
        OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
        return con.getInputStream();
    }

    public static String retornaClassificacao(InputStream inputStream) throws Exception{
        OutputStream outputStream = null;
        Tidy tidy = new Tidy();
        Document doc =  tidy.parseDOM(inputStream, outputStream);
        NodeList nodes = doc.getElementsByTagName("span");
        for(int i=0; i<nodes.getLength(); i++){
            Node node = nodes.item(i);
            Node att = node.getAttributes().getNamedItem("class");
            if(att.getNodeValue().equals("postdetails")){
                System.out.println(node.getFirstChild().getNodeValue());
            }
        }
        return "";
    }

    public static String exibirConteudoResponse(InputStream inputStream)throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        String retorno = "";
        while ((line = br.readLine()) != null) {
            retorno += line;
        }
        br.close();
        return retorno;
    }

    public static void main(String[] args) {
        try{
            retornainput();
            System.out.println(retornaClassificacao(retornaInputProfiller()));
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }
}

este código vai te mostrar classificação : tal, ai vc utiliza replace da classe string e pega só o conteudo.

link jtidy bom dar uma estudada em xml com java

http://jtidy.sourceforge.net/download.html

qualquer dúvida ou melhora ou qualquer coisa que seja produtiva (ehehe) é bem vindo ai viu. bye

R

fiz a conexão com o http do java e não por sockets, mas é só trocar pequenas coisas que vai funcionar com sockets

A

rjbcordeiro,

Eu gostaria de terminar da forma como comecei, pois a intenção é o aprendizado mesmo. Instalei a JTidy, e adicionei-a ao meu projeto. O que fiz até agora foi:

/********************************************************
 *             Robô HTTP Java - Versão 1.0
 *  Autor: André Rosa
 *  Criação: 29 de Julho de 2011, às 21:36
 *  Código aberto para estudo.  Favor, preservar
 *  os créditos do autor.
 *********************************************************/


package guj;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.Scanner;
import java.io.File;
import java.io.FileWriter;
import org.w3c.dom.Document;  
import org.w3c.dom.Node;  
import org.w3c.dom.NodeList;  
import org.w3c.tidy.Tidy; 

public class Main {


    public static void main(String[] args) throws IOException {

        /* Criação do objeto escreve, do tipo Filewriter */
        FileWriter escreve = new FileWriter(new File ("tmp.txt"), true);

        /* Criação de um objeto do tipo Scanner */
        Scanner en = new Scanner (System.in);
        System.out.print("Entre com o id: ");
        String endereco = en.nextLine();
        endereco = "http://www.guj.com.br/user/profile/"+endereco+".java";
        try{
            /* Criação de um objeto do tipo URL */
            URL site = new URL(endereco);
            URLConnection obj = site.openConnection();
            /* Criação do objeto de entrada de buffer */
            BufferedReader in = new BufferedReader(new InputStreamReader(obj.getInputStream()));
            String LinhaCod;
            while ((LinhaCod = in.readLine()) != null){
                escreve.write(LinhaCod);
            }
            /* Fecha o objeto */
            in.close();

            /* Fecha o objeto de escrita */
           escreve.close();
        } catch (Exception e){
            System.out.println(e);
            System.exit(1);
        }
    }

}

Pois bem, eu poderia jogar todo conteúdo deste txt em um ArrayList, e depois chamar este método getElementsByTagName()? Será que funcionaria?

Obrigado!

M

Uma dica. Já que você não vai precisar do arquivo poteriormente, pois ele é só para armazenamento temporário de informações, você pode usar um buffer de bytes no lugar do arquivo.

public static void teste() {
		byte[] buffer = new byte[2 * 1024 * 1024];// Cria um buffer de bytes de
													// 2Mb
		ByteArrayInputStream arrayInputStream;
		Scanner en = new Scanner(System.in);
		System.out.print("Entre com o id: ");
		String endereco = en.nextLine();
		endereco = "http://www.guj.com.br/user/profile/" + endereco + ".java";
		try {
			/* Criacao do objeto url */
			URL site = new URL(endereco);
			URLConnection obj = site.openConnection();
			/* Criacao do buffer de bytes*/
			InputStream in = obj.getInputStream();
			in.read(buffer, 0, buffer.length);//
			arrayInputStream = new ByteArrayInputStream(buffer);
			//Pode-se agora usa o bufferedReader para ler os dados do buffer de bytes
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(arrayInputStream));
			bufferedReader.close();
			in.close();

			/* Fecha o objeto de escrita */

		} catch (Exception e) {
			System.out.println(e);
			System.exit(1);
		}
}

Isso evita a dor de cabeça de ter que deletar o arquivo, que é algo que nem sempre dá certo no windows.

A

Mais uma vez, obrigado, Matheus. Eu estava pensando ontem como eu poderia apagar este arquivo, já que eu só tinha o objeto de escrita dele.

M

E às vezes você nem consegue apagar o arquivo. Se por acaso o arquivo estiver aberto em outro programa ou por algum motivo, algum processo do Windows que usava o arquivo não foi corretamente encerrado, você não vai coneguir apagar o arquivo.

Criado 29 de julho de 2011
Ultima resposta 30 de jul. de 2011
Respostas 32
Participantes 7