2012-04-20 32 views
5

Estoy tratando de crear una aplicación para raspar contenido de varias páginas de un sitio. Estoy usando JSoup para conectarme. Este es mi código:Manejo de errores de conexión y JSoup

for (String locale : langList){ 
     sitemapPath = sitemapDomain+"/"+locale+"/"+sitemapName; 
     try { 
      Document doc = Jsoup.connect(sitemapPath) 
        .userAgent("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.21 (KHTML, like Gecko) Chrome/19.0.1042.0 Safari/535.21") 
        .timeout(10000) 
        .get(); 

      Elements element = doc.select("loc"); 
      for (Element urls : element) { 
       System.out.println(urls.text()); 
       } 
     } catch (IOException e) { 
      System.out.println(e); 
     } 
    } 

Todo funciona perfectamente la mayor parte del tiempo. Sin embargo, hay algunas cosas que quiero poder hacer.

Primero, a veces se devuelve un estado 404 o un estado 500 tal vez un 301. Con mi código a continuación, simplemente imprimirá el error y pasará a la siguiente url. Lo que me gustaría poder hacer es tratar de devolver el estado de la url para todos los enlaces. Si la página se conecta imprime a 200, si no imprime el código de estado relevante.

En segundo lugar, a veces capto este error "java.net.SocketTimeoutException: tiempo de espera agotado para leer" Pude aumentar el tiempo de espera sin embargo prefiero intentar conectar 3 veces, al fallar la 3ª vez que deseo agregar la URL a un Matriz "fallida", por lo que puedo volver a intentar las conexiones fallidas en el futuro.

¿Puede alguien con más conocimiento que yo ayudarme?

Respuesta

15

Para su primera pregunta, se puede hacer la conexión/leer en dos pasos, deteniéndose para que solicite el código de estado en el centro de este modo:

Connection.Response response = Jsoup.connect(sitemapPath) 
         .userAgent("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.21 (KHTML, like Gecko) Chrome/19.0.1042.0 Safari/535.21") 
         .timeout(10000) 
         .execute(); 

int statusCode = response.statusCode(); 
if(statusCode == 200) { 
    Document doc = connection.get(); 
    Elements element = doc.select("loc"); 
    for (Element urls : element) { 
     System.out.println(urls.text()); 
    } 
} 
else { 
    System.out.println("received error code : " + statusCode); 
} 

Tenga en cuenta que el método execute() fallará con un IOException si no puede conectarse al servidor, si la respuesta es un HTTP mal formado, etc., entonces tendrá que manejar eso. Sin embargo, siempre que el servidor haya dicho algo que tenga sentido, podrá leer el código de estado y continuar. Además, si le pidió a Jsoup que siga los redireccionamientos, no verá los códigos de respuesta 30x b/c Jsoup configurará el código de estado de la página final recuperada.

En cuanto a su segunda pregunta, todo lo que necesita es un bucle alrededor de la muestra del código que acabo de darle que está envuelto en un bloque try/catch con SocketTimeoutException. Cuando atrape la excepción, el ciclo debería continuar. Si puede obtener datos, luego regrese o rompa. ¡Grite si necesita más ayuda!

+0

genera una excepción –

15

Lo anterior me devuelve una IOException en lugar de la ejecución() devolviendo el código de estado correcto.

Utilizando JSoup-1.6.1 tuve que cambiar el código anterior para usar ignoreHttpErrors(true).

Ahora cuando el código devuelve la respuesta en lugar de arrojar una excepción, puede verificar los códigos/mensajes de error.

Connection.Response response = null; 
      try { 
       response = Jsoup.connect(bad_url) 
         .userAgent("Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5") 
         .timeout(100000) 
         .ignoreHttpErrors(true) 
         .execute(); 
      } catch (IOException e) { 
       System.out.println("io - "+e); 
      } 

      System.out.println("Status code = " + response.statusCode()); 
      System.out.println("Status msg = " + response.statusMessage()); 

Salida:

Status code = 404 
Status msg = Not Found