Página 1 de 1

obtener HTML generado dinámicamente por jQuery

Publicado: 06 Feb 2017, 08:48
por tormund
Estoy tratando de hacer un scapper en Java para HDFull y me he encontrado con el problema de que la lista de enlaces a los vídeos se genera de forma dinámica, de forma que cuando me descargo la URL donde se muestran no aparece nada relativo a estos enlaces.

Por lo que he estado investigando se generan mediante una función jQuery a partir del evento onLoad. Inicialmente pensé que vosotros evaluabais este jQuery para obtener los enlaces pero al mirar en el código de la función "downloadpage" parece que no lo hacéis (digo parece porque de python estoy pegao), esto me hace pensar que debe haber alguna forma de obtener estos enlaces sin tener que evaluar este código jQuery. ¿Debo agregar alguna cabecera especial en la petición cuando descargue la página?

Si me pudierais arrojar un poco de luz os lo agradecería mucho porque estoy atascado en este punto.

Saludos.

Re: obtener HTML generado dinámicamente por jQuery

Publicado: 07 Feb 2017, 00:57
por robalo
Tu problema puede que sea los headers, o el método que estés usando para solicitar las páginas. Si esta parte la consigues controlar sólo tendrás que reproducir las llamadas y el scraped en java como haces con los conectores.

Re: obtener HTML generado dinámicamente por jQuery

Publicado: 08 Feb 2017, 08:15
por tormund
He cambiado las headers e incluso pedido el contenido en gzip pero sigue sin devolverme el contenido generado por jQuery. El método con el que estoy solicitando es "GET".

Estoy empezando a sospechar que sea una limitación de la librería que uso para descargar las páginas.

Saludos.

Re: obtener HTML generado dinámicamente por jQuery

Publicado: 08 Feb 2017, 23:14
por robalo
hdfull no tiene que cargar nada del jquery, repasa bien el code de la versión python.

Por ejemplo,"http://hdfull.tv/series/list" debería debería darte los datos para el scraped sin problemas sólo con el user-agent y referer.

Qué urls te da problemas y que datos intentas sacar de ellas?

Pásame algunas urls y los regex a usar y la testeo

Re: obtener HTML generado dinámicamente por jQuery

Publicado: 09 Feb 2017, 07:12
por tormund
No me ocurre en todas las páginas, sólo en las que se listan los enlaces a servidores de streaming de un capítulo o película, por ejemplo:

http://hdfull.tv/serie/the-grand-tour/t ... episodio-1

El problema no lo tengo al capturar estos enlaces (no uso RegEx, sino una librería de scrapping llamada Jsoup), sino que en el código que descargo no aparece esta lista de enlaces. En concreto obtengo esto (te pego sólo la parte de la que estamos hablando):

Código: Seleccionar todo

 <!-- MAIN WRAPPER --> 
   <div class="main-wrapper"> 
    <!-- MAIN CONTAINER --> 
    <div class="container-wrap"> 
     <div class="breakaway-wrapper" id="video-pages-wrapper"> 
      <div class="row-pages-wrapper"> 
       <div class="content"> 
        <div id="embed-list"></div> 
       </div> 
      </div> 
     </div> 
En el DIV "embed-list" debería ir algo así:

Código: Seleccionar todo

<div class="embed-selector" id="embed-selector-4384926" data-id="4384926" style="background-image: url("http://hdfull.tv/templates/hdfull/images/spa.png");">
<h5 class="left">
<span><b class="key"> Idioma:</b>Audio Español</span>
<span><b class="key">Servidor:</b><b class="provider" style="background-image: url("http://www.google.com/s2/favicons?domain=powvideo.net");">powvideo.net</b></span>
<span><b class="key">Calidad:</b>HDTV</span>
</h5>
<ul class="filter action-buttons">
<li class="current right">
<a class="danger" title="Reportar"><i class="icon-warning-sign icon-white"></i>&nbsp;</a>&nbsp;
<a href="/ext/ZXBpc29kZXw0Mzg0OTI2" target="_blank" title="Reportar"><i class="icon-share-alt icon-white"></i> Descargar </a>
</li></ul>
</div>
De hecho, si estoy en Firefox en esta página y pulso en "Ver código fuente", sigue sin aparecerme este código, sólo lo veo si uso el inspector de código del modo desarrollador. En este inspector se indica que este código ha sido generado a partir de un evento que llama a la librería jQuery.hdfull.view.min.js.

Ayer me bajé la versión de pelisalacarta que tiene Cmos en Github y al menos en esta versión tampoco se listan los servidores para HDFull, pero es bastante probable que no lo haya hecho bien y me haya bajado la versión que no es (me bajé la que hay en la carpeta main-classic).

He leído el código vuestro en Python y efectivamente no evaluáis ningún jQuery, de ahí mi confusión al ver que simplemente descargando el código no obtengo el código esperado.

Las headers que uso serían:

Código: Seleccionar todo

conexion.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0");
            conexion.setRequestProperty("Referer", "http://hdfull.tv");
            conexion.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
            conexion.setRequestProperty("Accept-Language", "es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3");
            conexion.setRequestProperty("Accept-Charset", "UTF-8");
            conexion.setRequestProperty("Accept-Encoding", "gzip");
            conexion.setRequestProperty("Connection", "keep-alive");
            if (!cookie.isEmpty()) {
                conexion.setRequestProperty("Cookie", cookie);
            }
Saludos.

Re: obtener HTML generado dinámicamente por jQuery

Publicado: 09 Feb 2017, 18:10
por Cmos
La web no te está cargando mal ni se necesitan más headers tormund, la página por sí sola no contiene ningún enlace ni genera el apartado embed-list con la calidad, etc...así es como lo hacía antes pero con la última modificación hay desofuscar el código para ver el contenido. Este es el último hdfull publicado: https://github.com/CmosGit/pelisalacart ... /hdfull.py

Fíjate en la función findvideos, en ella se descargan dos .js, el que tú no has nombrado y un provider.js. Del primero se extrae la key para el método que desencripta. Este método está al final del todo, función obfs, en la cual el parámetro data se saca de la web normal de hdfull, scrapeando la variable ad, y el resultado devuelto es un dict. Al segundo js hay que pasarlo por la función jhexdecode para que sea legible y sirve como plantilla para interpretar los datos desencriptados y extraer la url completa, calidad, idioma, etc.

Creo que si vas siguiendo el flujo del código no es muy complicado de entender, pero si hay algo que no te queda claro aquí estamos ;)

Re: obtener HTML generado dinámicamente por jQuery

Publicado: 09 Feb 2017, 18:38
por tormund
Vale, ahora todo tiene sentido. Lo que me estaba volviendo loco es que al ver que no me cargaba los enlaces me fui a la última versión de vuestro código y observé cómo lo hacíais en la función findvideos. Cuando no encontré ninguna referencia a los js pensé que estaba enviando mal la petición para descargar el HTML, sin embargo cuando iba a Firefox veía que se llamaba al js que os mencioné.

Sois los putos amos.

Mil gracias.

Re: obtener HTML generado dinámicamente por jQuery

Publicado: 10 Feb 2017, 00:19
por robalo
Una parte para la url que has posteado podria ser como lo siguiente:

getDataFromUrl.java

Código: Seleccionar todo

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;

public class getDataFromUrl {

	String data;

	getDataFromUrl(String pageUrl, String[] headers) {

		StringBuilder sb = new StringBuilder();
		URLConnection urlConn = null;
		InputStreamReader in = null;

		int c = 0;
		String key = "";
		String value = "";

		try {
			URL getUrl = new URL(pageUrl);
			urlConn = getUrl.openConnection();
			for (String header : headers) {
				if (c % 2 == 0)
					key = header;
				else {
					value = header;
					urlConn.addRequestProperty(key, value);
				}
				c++;
			}
			if (urlConn != null)
				urlConn.setReadTimeout(60 * 1000);
			if (urlConn != null && urlConn.getInputStream() != null) {
				in = new InputStreamReader(urlConn.getInputStream(),
						Charset.defaultCharset());
				BufferedReader bufferedReader = new BufferedReader(in);
				if (bufferedReader != null) {
					int cp;
					while ((cp = bufferedReader.read()) != -1) {
						sb.append((char) cp);
					}
					bufferedReader.close();
				}
			}
			in.close();
		} catch (Exception e) {
			throw new RuntimeException("Exception getDataFromUrl:" + pageUrl, e);
		}

		data = sb.toString();

	}
}
hdfull.java

Código: Seleccionar todo

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.bind.DatatypeConverter;

public class hdfull {

	String dataHtml;

	hdfull(String pageUrl) {

		String host = "http://hdfull.tv";
		String[] headers = {
				"User-Agent",
				"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0",
				"Referer", host };

		String data = new getDataFromUrl(pageUrl, headers).data;

		String patron = "";
		Matcher matches;

		patron = "var ad\\s*=\\s*'([^']+)'";
		matches = Pattern.compile(patron).matcher(data);

		String data_obf = "";
		while (matches.find())
			data_obf = matches.group(1);

		String decode = new String(DatatypeConverter.parseBase64Binary(data_obf));
		String data_decrypt = obfs(decode, 15);

		dataHtml = data_decrypt;
	}

	private static String obfs(String data, Integer key){

		Integer n = 126 - key;
		String[] chars = data.split("");

		String ret = "";
		for(Integer i=0; i<chars.length; i++){
			try{
				Integer c = Character.codePointAt(chars[i], 0);
				if(c < 126){
					chars[i] = new String(Character.toChars((c + n) % 126));
					ret += chars[i];
				}
			}
			catch (Exception e) {}
		}
		return ret;
	}
}
testHdfull.java

Código: Seleccionar todo

public class testHdfull {

	public static void main(String[] args) {

		String pageUrl = "http://hdfull.tv/serie/the-grand-tour/temporada-1/episodio-1";
		String data = new hdfull(pageUrl).dataHtml;
		System.out.println(data);
	}
}
Consola

Código: Seleccionar todo

[{"id":"4384926","provider":"1","code":"9n3r6v0p1hsz","lang":"ESP","quality":"hdtv"},{"id":"4384921","provider":"2","code":"vkf89qk3tp1u","lang":"ESP","quality":"hdtv"},{"id":"4384929","provider":"5","code":"hgq5gkstsmgp","lang":"ESP","quality":"hdtv"},{"id":"4384928","provider":"12","code":"fvt2x449o0xc","lang":"ESP","quality":"hdtv"},{"id":"3981785","provider":"1","code":"hlttfncr4x1q","lang":"ESPSUB","quality":"hd720"},{"id":"3981775","provider":"2","code":"abai5ihyjqky","lang":"ESPSUB","quality":"hd720"},{"id":"3981776","provider":"5","code":"8c93g1894n97","lang":"ESPSUB","quality":"hd720"},{"id":"4368556","provider":"11","code":"mpxy0clkmeiv","lang":"ESPSUB","quality":"hd720"},{"id":"4367858","provider":"11","code":"mpxy0clkmeiv","lang":"ESPSUB","quality":"hd720"},{"id":"3964547","provider":"1","code":"35in6dol2qek","lang":"ENGSUB","quality":"hdtv"},{"id":"3964545","provider":"2","code":"7qkxwy07wytd","lang":"ENGSUB","quality":"hdtv"},{"id":"3964546","provider":"5","code":"tu572hgm5eek","lang":"ENGSUB","quality":"hdtv"},{"id":"4368963","provider":"11","code":"jvcqgd2vllv7","lang":"ENGSUB","quality":"hdtv"},{"id":"3964553","provider":"18","code":"3387975d71670","lang":"ENGSUB","quality":"hdtv"},{"id":"3956388","provider":"2","code":"aflv132itcug","lang":"ENG","quality":"hdtv"},{"id":"4839623","provider":"3","code":"oPC7wIypv5U","lang":"ENG","quality":"hdtv"},{"id":"4674227","provider":"4","code":"9o9aqywbp48d","lang":"ENG","quality":"hdtv"}]
Con algo más o menos como lo anterior y el 'providers' lo tienes casi hecho

Re: obtener HTML generado dinámicamente por jQuery

Publicado: 10 Feb 2017, 07:10
por tormund
He conseguido obtener los provider y desofuscar la variable ad pero hay un paso que no termino de entender. Cuando ya se ha obtenido los datos de la variable "providers" a través del jjHexDecode realizáis un "eval" sobre estos datos. Lo he intentando pero este "eval" me genera un error (SyntaxError: missing ; before statement), sin embargo creo que podré cargar los datos en un JSON sin necesidad de este "eval". Quería preguntaros para qué lo evaluáis ya que la salida que obtengo sin hacerlo creo que me sirve. Es algo así:

Código: Seleccionar todo

{43:
		{"t":"s",
		"d":"http://allvid.ch",
		"e":'function(var_1,var_2,var_3,var_4){return buildIframeEmbed("http://allvid.ch/embed-"+ var_1+ "-"+ var_2+ "x"+ var_3+ ".html",var_2,var_3,false)}',
		"l":'function(var_1,var_5){return "http://allvid.ch/"+ var_1}'},
                 .
                 .
                 .
                 }
Lo he resumido mucho para no dejar aquí el chorizaco.

Por lo que he visto sólo tengo que sustituir la variable var_1 de la función de "l" por el code de los providers, pero como no he aplicado el "eval" me preocupa haberme dejado algo atrás.

Saludos.