PDA

Ver la Versión Completa : Parsear contenido HTML


lsanchez
27-07-2015, 19:21:51
Buen día con todos,
Tengo una duda de hace algunos días, he rebuscado por el foro como ponerle fin a esto sin resultado.
Aquí voy,
Tengo hecho un programita el cual consulta una pagina web a partir de la inserción unos parametros de consulta y un captcha mediante POST, ingresado esto me arroja una información en tabla. Hasta aquí todo bien, pues la almaceno en una variable.
Mi problema incia al querer "discernir o procesar" esta información, necesito capturar los nombres de las columnas y el contenido de las filas, mas no traerme el código de la web. Tengo entendido que el método de solución a esto sería parsear, pero no lo eh comprendido bien, pues estos buscan etiquetas o nombres del campo, pero en mi caso la info que obtengo no se da de esa manera. Quisiera me puedan ayudar, subo mi código y la web que me traigo como resultado.
Gracias de antemano por su tiempo, saludos.


unit leer_numeracion;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,fphttpclient,Process,
ExtCtrls;
const
{$IFDEF UNIX}
ruta_trabajo='/tmp/';
comando_ocr='/usr/local/bin/tesseract ';
{$ENDIF}
{$IFDEF WINDOWS}
ruta_trabajo='d:\temp\';
comando_ocr='x:\sistemas\tesseract\tesseract.bat ';
{$ENDIF}

type

{ TForm1 }

TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Edit8: TEdit;
Limpiar: TButton;
Edit1: TEdit; //URL CAPTCHA
Edit2: TEdit; //URL WEB
Edit3: TEdit; //CODIGO ADUANA
Edit4: TEdit;
Edit5: TEdit;
Edit6: TEdit;
Edit7: TEdit;
Image1: TImage;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
Memo1: TMemo;
Memo2: TMemo;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure LimpiarClick(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;

var
Form1: TForm1;
codigo_captcha,coco:string; //VARIABLES GLOBALES

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject); // INICIO BOTON CAPTCHA
var
httpz:TFPHTTPClient;
data1:TMemoryStream;
nombre_img,nombre_txt,url_captcha:string;
cade:string;
comando:string;
proceso:Tprocess;
Captcha1:Tstringlist;
begin
//TEXTO
nombre_txt:='TC';
nombre_txt:='d:\'+nombre_txt+formatdatetime('YYYY_MM_DD_hhnnss',now);
//IMAGEN
nombre_img:='IC';
nombre_img:='d:\'+nombre_img+formatdatetime('YYYY_MM_DD_hhnnss',now)+'.jpg';
data1:=Tmemorystream.Create;
httpz:=TFPHTTPClient.Create(nil);

httpz.AddHeader('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64) '+
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36');

url_captcha:=edit1.text ; //OBTIENE URL CAPTCHA
try
httpz.Get(url_captcha,data1); // OBTIENE EL CAPTCHA DE URL Y LA ALMACEA EN DATA1
data1.SaveToFile(nombre_img); // GRABA IMAGEN
coco:=httpz.Cookies.Text; // ALMACENA LA COOKIE
memo2.Text:=coco; // MUESTRA LA COOKIE
image1.Picture.LoadFromFile(nombre_img); // CARGA IMAGEN EN FORMULARIO
finally
data1.Free;
httpz.free;
end;
comando:=comando_ocr+nombre_img+' '+nombre_txt+' -psm 8 letters'; // LINEA DE COMANDO
try
Proceso := TProcess.Create(nil);
Proceso.CommandLine:=comando;
{$IFDEF UNIX}
proceso.Environment.Add('TESSDATA_PREFIX=/usr/local/share');
{$ENDIF}
// Proceso.Options := Proceso.Options + [poWaitOnExit, poStderrToOutPut,poUsePipes];
Proceso.Options := Proceso.Options + [poWaitOnExit,poUsePipes];
Proceso.ShowWindow:=swoHIDE;
Proceso.Execute;
except on e:Exception do
showmessage('error:'+e.message);
end;
Captcha1:=tstringlist.Create;
cade:='';
if fileexists(nombre_txt+'.txt') then
begin
Captcha1.LoadFromFile(nombre_txt+'.txt'); // CARGA TXT Y LEE
cade:=Captcha1.text; // ALMACENA SU VALOR EN CADE
codigo_captcha:=cade;
edit7.text:=cade; // MUESTRA EL VALOR DE CADE EN CAMPO
end;
end; //FIN BOTON CAPTCHA

procedure TForm1.Button2Click(Sender: TObject); //INICIO BOTON WEB
var
http2:TFPHTTPClient;
data2:Tstringstream;
cadena:string;
url_web,cod_aduana:string;
begin
url_web:=Edit2.Text;// OBTIENE URL WEB
cod_aduana:=Edit3.Text;
// CADENA POST
cadena:='valueCmbOpe=&valueRegimen=10&CG_cadu='+cod_aduana+'&tipusua=1&CG_c'+
'age=0659&cg_creg=10&cGcop Manif=00&cGcopDuim=00&cGcopManifEER=00&'+
'codigo='+codigo_captcha+'&cG_fecha=&cG_fano=&cG_norden=';

http2:=TFPHTTPClient.Create(nil);
http2.AddHeader('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64) '+
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36');

http2.AddHeader('Connection', 'keep-alive');
data2:=Tstringstream.Create('');
http2.Cookies.Text:=coco;
http2.RequestHeaders.Add('application/x-www-form-urlencoded');
http2.AddHeader('Connection', 'keep-alive');
try
http2.FormPost(url_web,cadena,data2); // URL, CADENA , RESPUESTA
//DATA2 CONTIENE RESULTADO DE WEB HTML
Memo1.Text:=data2.DataString; // MOSTRANDO RESPUESTA HTML
//¿PARSEAR CONTENIDO DE DATA2?
finally
data2.Free;
http2.Free;
end;
end; // FIN BOTON WEB


Código HTML capturado


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>CONSULTA DE ENVIOS DE TELEDESPACHO</title>
<script language="javascript" src="/aduanas/js/diseno.js"></script>
<script language=javascript>document.write(cab_pag("CONSULTA DE ENVIOS DE TELEDESPACHO"))</script>
<script language='javascript' src='/aduanas/js/libpopup.js'></script>
<style type='text/css'><!--
.hand {cursor: hand;}
.detalle { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 9px;
font-style: normal; font-weight: normal; color: #000000;}
-->
</style>
</head>
<body>
<TABLE WIDTH='100%' border font-size: x-small>

<TR VALIGN=top>
<TD WIDTH='4%' BGCOLOR='e1e1e1'><font size=1><CENTER><P><B>
<a class='hand' onMouseOut='kill()' onMouseOver="popup('<span class=detalle ><p>T:CORREO TCI<BR>P:MAILWARE ADUANAS<BR>S:MAILWARE ASOCIACION DE AGENTES<BR>M:MAILWARE COURIER ADUANAS<BR>I:CORREO INTERNET<BR>C:CORREO CORPORATIVO<BR>D:CORREO USANDO DISKETTE<BR>W:TELEDESPACHO WEB<BR></p></span>','#FFFFCC','T')">Correo</a></B></p></CENTER></font></TD>
<TD WIDTH='6%' BGCOLOR='e1e1e1'><font size=1><P><CENTER><B>Orden </B></CENTER></P></font></TD>
<TD WIDTH='7%' BGCOLOR='e1e1e1'><font size=1><CENTER><P><B>Fecha </B></P></CENTER></font></TD>
<TD WIDTH='7%' BGCOLOR='e1e1e1'><font size=1><CENTER><P><B>Hora </B></P></CENTER></font></TD>
<TD WIDTH='8%' BGCOLOR='e1e1e1'><font size=1><CENTER><P><B>Archivo </B></P></CENTER></font></TD>
<TD WIDTH='7%' BGCOLOR='e1e1e1'><font size=1><CENTER><P><B>Declarac.</B></p></CENTER></font></TD>
<TD WIDTH='6%' BGCOLOR='e1e1e1'><font size=1><CENTER><P><B>Serie</B></p></CENTER></font></TD>
<TD WIDTH='6%' BGCOLOR='e1e1e1'><font size=1><CENTER><P><B>Item</B></p></CENTER></font></TD>
<TD WIDTH='6%' BGCOLOR='e1e1e1'><font size=1><CENTER><P><B>Tipo Trans/Env&iacute;o</B></p></CENTER></font></TD>
<TD WIDTH='10%' BGCOLOR='e1e1e1'><font size=1><CENTER><P><B>Gu&iacute;a Postal</B></p></CENTER></font></TD>
<TD WIDTH='30%' BGCOLOR='e1e1e1'><font size=1><CENTER><P><B>Observaci&oacute;n</B></p></CENTER></font></TD>
</TR>

<TR bgcolor='#FFFFFF'>
<td align="center"><font size=2>W</font></td>
<td align="center"><font size=2>003797</font></td>
<td align="center"><font size=2>17/07/2015</font></td>
<td align="center"><font size=2>15:01:30</font></td>

<td align="center"><font size=2>00920709&nbsp;</font></td>

<td align="center">
------

</td>
<td align="center"><font size=2>------</font></td>
<td align="center"><font size=2>------</font></td>
<td align="center">
<font size=2>05

</font>&nbsp;
</td>
<td align="center"><font size=2>------</font></td>
<td>
9074 : &nbsp; ( Advertencia de Rectificación ) &nbsp;SECUP:1 BDUAHDR1.Codi_Prove:<br> ** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CODIGO DE PROVEEDOR EXTRANJERO NO EXISTE, VERIFICAR EN EL PORTAL ADUANERO</br>

</td>
</TR>

<TR bgcolor='#FFFFFF'>
<td align="center"><font size=2>W</font></td>
<td align="center"><font size=2>003797</font></td>
<td align="center"><font size=2>17/07/2015</font></td>
<td align="center"><font size=2>15:01:41</font></td>

<td align="center"><font size=2>00920709&nbsp;</font></td>

<td align="center">
------

</td>
<td align="center"><font size=2>------</font></td>
<td align="center"><font size=2>------</font></td>
<td align="center">
<font size=2>05

</font>&nbsp;
</td>
<td align="center"><font size=2>------</font></td>
<td>
9204 : &nbsp; ( Advertencia de Rectificación ) &nbsp;DUAHDR.DIRE_IMPOR-20508565934-dirección diferente al registrado<br> ** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MODIFICACIÓN IMPROCEDENTE, NO SERÁ CONSIDERADA</br>

</td>
</TR>

</body>
</html>

Ñuño Martínez
11-08-2015, 10:23:37
Si es XHTML, HTML4 ó HTML5 podrías intentar procesarlo como un XML. Hay varias bibliotecas por ahí que lo hacen, aunque los dos últimos puede que no lo pillara bien. Otras versiones de HTML son más complicadas.

Lo único que he encontrado es este tutorial de procesamiento XML para Lazarus (http://wiki.freepascal.org/XML_Tutorial). Con suerte puede que te sirva.

mamcx
11-08-2015, 19:11:13
No, no.

Usar XML para parsear HTML es UN ERROR.

HTML es una bestia animal muy distinta. Se requiere un parser especifico para html. El termino general es "Web Scrapping"

Hice un tutorial basico en python:

http://code.runnable.com/UryhiPR1U0BKAAMO/how-do-web-scrapping-with-python-baby-steps-for-tutorial-beginner-scraping-scrapy-beautifulsoup-requests-html-and-wikipedia

Osea:

1- Necesitas un parseador HTML.

A menos que la pagina sea super-estatica y tengas control sobre ella (ie: Mucha seguridad de que no cambiara) no hay vuelta con esto

2- Necesitas usando el parseador, acertar a los tags correctos

La otra, y mejor, si tienes acceso o puedes conseguir la colaboracion de los dueños de la pagina, es que hacer un API rest que te de los datos que realmente necesitas

lsanchez
12-08-2015, 15:56:32
Exacto, es la razón por la que no use el XML para parsear. No encontré mucha info por no decir nada acerca de hacerlo en HTML para delphi. Sin embargo, me base de unas funciones y procedimientos para quitar todo el código HTML (LO QUE NO NECESITO), sé que no es la forma correcta ni mas adecuada, ya que si la página web de donde extraigo esta data sufre alguna alteración o modificación, me veré forzado también yo a modificar mi fuente, pero no tenía de otra. Compartiría la fuente, pero no se me permite subir adjuntos.
Ahora estoy en otra etapa en la que necesitaría alguna ayudita de ser posible, es con la insercción de los datos a oracle:
clubdelphi.com/foros/showthread.php?t=88839
Y con respecto a conseguir ayuda de los creadores de la página, lo dudo, ya que lo que estoy haciendo es llevarme la data saltando su seguridad :D