PDA

Ver la Versión Completa : Automatización Web (HTTP sin navegador)


Al González
31-10-2006, 23:26:07
¡Hola a todos!

Quisiera saber si alguno de ustedes ha programado algo de automatización Web y qué me aconsejaría para poder implementar ésta en una aplicación Delphi 7 Win32.

Quiero automatizar la operatividad de una página Web, hacer un pequeño robot que:

Acceda a la página.
Ingrese la clave de usuario y contraseña requeridas.
Ingrese a determinada sección del sitio Web.
Envíe al servidor Web el valor de determinados datos que la página solicita (método Post o Get del protocolo HTTP).
Reciba del servidor Web la página o datos resultantes de la consulta.
Extraiga (análisis sintáctico —parse— sobre el stream HTML recibido) los datos relevantes de la consulta (para después almacenarlos en una base de datos).
Repita sucesivamente los pasos 4, 5 y 6 para consultar más información en base a otros valores de entrada (ciclo automático de consulta).


Todo esto sin la necesidad de desplegar la página, es decir, sin utilizar un navegador ni intervención alguna del usuario. Mi aplicación Delphi teniendo comunicación HTTP con el servidor Web de la página.

He visto que hay algunos componentes Delphi (http://www.torry.net/pages.php?id=215) que permiten implementar soluciones como la que planteo, incluso he leído que algunos tienen la capacidad de hacer el envío de datos al servidor Web tanto por el método Post como por el método Get, pero me gustaría partir de la experiencia y recomendaciones que amablemente me hagan al respecto.

De antemano muchas gracias.

Un abrazo sin protocolo.

Al González. :)

seoane
01-11-2006, 00:13:32
Hola Al, la verdad es que la frase "... pero me gustaría partir de la experiencia ..." impone mucho, sobre todo a los que tenemos poca :) . Además viniendo la pregunta de quien viene me temo que no es una pregunta de principiante y necesitas respuestas con contenido. Pero por alguna parte habrá que empezar y ya veremos hasta donde llegamos.

Supongo que ya habrás hecho un búsqueda por los foros, ¿has revisados estos hilos?

http://www.clubdelphi.com/foros/showthread.php?t=34263
http://www.clubdelphi.com/foros/showthread.php?t=34666

¿Buscas algo parecido? ¿buscas algo diferente? ¿puede servirte, pero necesitas ampliarlo?

Vamos a ver hasta donde podemos llegar ... A menos que por aquí haya alguien con experiencia que nos de una solución mejor :D

dec
01-11-2006, 00:19:32
Hola,

Puedes utilizar el componente "TIdHttp" de los "Indy (http://www.indyproject.org/)". Es un cliente HTTP que te permitirá requerir un recurso (GET), enviar datos (POST), etc. No tiene nada que ver con el "TWebBrowser", es decir, en ningún momento precisarás mostrar el resultado de tus consultas.

Cuando realizas una petición "GET" puedes obtener el resultado como un sencillo "Stream", no necesitas, por tanto, volcar dicho contenido (sea HTML o sea el que sea) en ningún sitio. Puedes, por tanto, "parsearlo", guardarlo, en fin, lo que necesites.

"Parsers" de HTML hay varios... creo recordar. Será cuestión de que eches un vistazo por Torry's (http://www.torry.net/) o alguna página similar. Creo que las "Jedi (http://www.delphi-jedi.org/)" incluyen algún "parser HTML", por si acaso instalaste estos componentes y no quieres ponerte a buscar ninguno aparte.

No sé si lo que he dicho te sirve como aproximación... acaso algún compañero pueda añadir algo más. Tú ya sabes que puedes replicar lo que te sea menester que por aquí estamos. ;)

jachguate
01-11-2006, 02:11:07
Hola Al.

A la excelente explicación de dec, solamente hará falta añadir que regularmente los sitios manejan una "sesión", cuyo ID guardan en una galleta (cookie) y requieren de este para poder reconocer que usuario ha iniciado sesión y si esta no ha expirado.

Esto también podes manejarlo con las Indy, que cuentan con la maquinaria necesaria para esta tarea: TidCookieManager, que luego asocias a la propiedad CookieManager del ya mencionado TidHTTP.

Finalmente comentar que no hace falta que bajes la página de login cada vez que realices el paso 1/2 de tu explicación. Basta con que realices la llamada -normalmente un POST- que ejecutaría el navegador cuando un usuario humano haga clic en el botón "login", y estes atento a recibir y almacenar (puede ser en memoria) el cookie correspondiente a la sesión.

Claro que esta es la generalidad de los casos, pero puede haber páginas que implementen en reconocimiento del usuario de alguna otra manera, para ellas habrá que hacer algo de análisis de comportamiento, pero siempre son cosas que pueden manejarse desde delphi.

Hasta luego.

;)

seoane
01-11-2006, 21:05:45
Bueno, como alternativa a Indy podemos usar Wininet. Podemos hacer Get, podemos hacer Post y maneja las cookies perfectamente incluso las de sesión. No tengo nada en contra de las Indy, es solo por dar alternativas, además no se pueden usar en el Turbo :mad: , aunque eso no es culpa suya.

Bueno, un poco de código para animar la cosa:

uses Windows, SysUtils, Classes,Wininet;

// URL Encode y Decode para codificar los strings segun la norma RFC 1738
function URLEncode(Str: string): string;
var
i: integer;
begin
Result:= '';
for i:= 1 to Length(Str) do
if Str[i] in ['A'..'Z','a'..'z','0'..'9','-','_','.'] then
Result:= Result + Str[ i ]
else
Result:= Result + '%' + IntToHex(Ord(Str[ i ]),2);
end;

function URLDecode(Str: string): string;
var
i: integer;
begin
Result:= '';
Str:= StringReplace(Str, '+', ' ', [rfReplaceAll]);
while Length(Str) > 0 do
begin
if Copy(Str, 1, 1) = '%' then
begin
if not TryStrToInt('$' + Copy(Str, 2, 2),i) then
begin
Result:= '';
Exit;
end;
Result:= Result + Char(i);
Delete(Str, 1, 2);
end else Result:= Result + Copy(Str, 1, 1);
Delete(Str,1,1);
end;
end;

// Con esta funcion hacemos Get y nos devuleve el resultado en un stream
function Get(Url: string; Stream: TStream): Boolean;
var
hNet: HINTERNET;
hUrl: HINTERNET;
Buffer: array[0..10240] of Char;
BytesRead: Cardinal;
begin
Result:= FALSE;
hNet:= InternetOpen('Agente', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
if (hNet <> nil) then
begin
hUrl:= InternetOpenUrl(hNet, PChar(Url), nil, 0,
INTERNET_FLAG_RELOAD, 0);
if (hUrl <> nil) then
begin
while (InternetReadFile(hUrl, @Buffer, sizeof(Buffer), BytesRead)) do
begin
if (BytesRead = 0) then
begin
Result:= TRUE;
break;
end;
Stream.Write(Buffer,BytesRead);
end;
InternetCloseHandle(hUrl);
end;
InternetCloseHandle(hNet);
end;
end;

// Con esta funcion hacemos Post, los campos del formulario se pasan en PostString
// como pares nombre=valor
function Post(Servidor, Pagina: string; Puerto: Word;
PostStrings: TStringList; Stream: TStream): Boolean;
var
hNet: HINTERNET;
hCon: HINTERNET;
hReq: HINTERNET;
Context: DWORD;
Str: string;
i: integer;
Buffer: array[0..10240] of Char;
BytesRead: DWORD;
begin
Context:= 0;
Result := FALSE;
Str:= '';
hNet := InternetOpen('Agente', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
if (hNet <> nil) then
begin
hCon:= InternetConnect(hNet,PChar(Servidor),Puerto,nil,nil,
INTERNET_SERVICE_HTTP,0,Context);
if (hCon <> nil) then
begin
hReq:= HttpOpenRequest(hCon,'POST',PChar(Pagina),nil,nil,nil,
INTERNET_FLAG_RELOAD,Context);
if (hReq <> nil) then
begin
for i:= 0 to PostStrings.Count - 1 do
begin
Str:= Str + '&' + URLEncode(PostStrings.Names[i]) + '=' +
URLEncode(PostStrings.ValueFromIndex[i]);
end;
Delete(Str,1,1);
try
if HttpSendRequest(hReq,
'Content-Type: application/x-www-form-urlencoded',Cardinal(-1),
PChar(Str),Length(Str)) then
begin
while (InternetReadFile(hReq,@Buffer,sizeof(Buffer),BytesRead)) do
begin
if (BytesRead = 0) then
begin
Result := TRUE;
break;
end;
Stream.Write(Buffer,BytesRead);
end;
end;
except end;
InternetCloseHandle(hReq);
end;
InternetCloseHandle(hCon);
end;
InternetCloseHandle(hNet);
end;
end;


Ahora que ya podemos hacer Get y Post solo nos falta analizar las paginas que obtenemos :confused: ¿voy por buen camino?

EDITO:
Modifico la función Post para incluir la cabecera Content-Type, que al parecer es necesaria, al menos para el siguiente ejemplo:

Entrar al ClubDelphi, iniciar sesión y obtener la pagina principal de los foros:

procedure Ejemplo;
var
Campos: TStringlist;
Stream: TMemoryStream;
begin
Campos:= TStringList.Create;
Stream:= TMemoryStream.Create;
try
Campos.Values['vb_login_username']:= 'usuario';
Campos.Values['vb_login_password']:= 'password';
Campos.Values['submit']:= 'Ingresar';
Campos.Values['s']:= '';
Campos.Values['do']:= 'login';
Post('www.clubdelphi.com','/foros/login.php',80,Campos,Stream);
Stream.Clear;
Get('http://www.clubdelphi.com/foros/',Stream);
Stream.SaveToFile('d:\1.txt');
finally
Campos.Free;
Stream.Free;
end;
end;

Al González
01-11-2006, 21:24:48
¡Hola a todos!

Gracias Seoane, David y Antonio por la información que me proporcionan. Este viernes evaluaré sus sugerencias y haré las primeras pruebas. Los mantendré informados de mis avances para que el curso de esta solución (el hilo en sí) sea una experiencia de la que puedan aprender otros desarrolladores que se encuentren en la misma vicisitud.

Un abrazo telarañudo.

Al González. :)

dec
01-11-2006, 21:25:35
Hola,


¿voy por buen camino?


Pues yo creo que sí, vamos. Está muy bien Seoane. :)

dec
01-11-2006, 21:32:15
Hola,

Román, personalmente también pienso que utilizar las Indy puede ser más razonable, empero, estarás conmigo en que el código fuente es una maravilla, que acaso en ocasiones sea mejor (en varios aspectos y por diversos motivos) utilizar, directamente, el API WinInet. Yo desde luego me he permitido añadir el código entre el resto de Trucos (http://www.clubdelphi.com/trucos/), con el permiso de Seoane, pues que creo que puede ser un código fuente muy útil.

Ahora, ¿que por eso digo que las Indy no debieran usarse? Nada de eso, de hecho ya he dicho que me parece más razonable usarlas, siempre que sea posible; pero también digo que no viene de más tener otras opciones, que ratón que conoce un agujero sólo pronto le caza el gato (o algo así). :)

¿Que no? :D

dec
01-11-2006, 21:44:18
Hola,

Estoy de acuerdo contigo Román. Más ahora que sé que puede funcionar mejor incluso. Empero, lo dicho dicho, una cosa no quita la otra. En realidad creo que estamos de acuerdo todos, incluído el propio Domingo. :)

seoane
01-11-2006, 22:16:00
:D Vaya me levanto para cenar algo y como se animo la conversación. Vamos ir por partes como dijo Jack.

¿Que no puedes usar las Indy en TurboExplorer? ¿Y quién dice que no?

Yo no dije nunca lo contrario, de hecho al poquito tiempo de salir los turbo comente por aqui (http://www.clubdelphi.com/foros/showpost.php?p=155373&postcount=67) que se podían usar las Indy por código.

No puedes incrustarlas en un formulario y asignar sus propiedades con el Inspector de objetos, pero sí puedes instanciarlas manualmente, y que yo sepa eso es legal. Siendo componentes no visuales, no es mucha la carga de hacerlo a pie

No, no resulta mucho trabajo hacerlo a mano, pero tampoco mucho menos que hacerlo con Wininet.

Por otra parte, wininet es una api de "alto nivel" para facilitar el uso de los protocolos tcp, pero esto mismo hace que no sea tan eficiente como las componentes indy que usan dichos protocolos a "bajo nivel"

Hombre, cual de los 2 es mas eficiente seria discutible. Si bien es verdad que el código de las Indy es impecable, también es verdad que se a convertido en un gigante, con múltiples propiedades, eventos, etc ... solo hay que ver el par de cientos de Kb que añade al ejecutable para ver su envergadura. Además no hay razón para suponer que el código de microsoft desde que se hace una petición http hasta el Winsock, de muchas mas vueltas que Indy desde que hacemos una petición http hasta el winsock (Indy también hace uso del winsock, es todo lo abajo que llega :) ). Tendríamos que hacer pruebas, pero apuesto a que wininet podría obtener tiempos iguales o mejores que Indy.

Y por ultimo algo mas subjetivo, me gusta mas el Wininet :D que le vamos a hacer. Pero si bien es verdad me he fijado que en este foro suele gustar mucho mas las Indy, así que supongo que serán mejores, pero yo todavía no he visto que ofrezca grandes ventajas, al menos en aplicaciones cliente, no así si queremos hacer, por ejemplo, un servidor. Pero eso ya es otra historia ...

dec
01-11-2006, 22:21:49
Hola,

Las ventajas que ofrecen las Indy deben ser, sin duda, la orientación a objetos, esto es, que son un conjunto de componentes y clases que te permiten trabajar manipulando propiedades, invocando métodos, respondiendo a eventos, etc.

Ahora bien, mirando el código que has presentado Seoane dan ganas en encapsularlo y presentarlo en una clase. En todo caso creo que puede resultar muy útil. ;)

tefots
02-11-2006, 11:47:54
volviendo al tema

aqui pongo un ejemplo de como hacer un post usando las indy.
creo que es mas sencillo que usando las wininet.

el get seria parecido.


procedure TForm1.SendPostData;
Var
aStream: TMemoryStream;
Params: TStringStream;
begin
aStream := TMemoryStream.create;
Params := TStringStream.create('');

try
with IdHTTP1 do
begin
Params.WriteString(URLEncode('teste=' + 'yes' + '&'));
Params.WriteString(URLEncode('name=' + 'ivan' + '&'));
Params.WriteString(URLEncode('number=' + '102'));
Request.ContentType := 'application/x-www-form-urlencoded';
try
Post('http://localhost/teste.asp (http://localhost/teste.asp)', Params, aStream);
except
on E: Exception do
showmessage('Error encountered during POST: ' + E.Message);
end;
end;
aStream.WriteBuffer(#0' ', 1);
aStream.Position := 0;
Memo1.Lines.LoadFromStream(aStream);
except
end;
end;

seoane
02-11-2006, 17:32:03
Por favor Roman llámame Domingo que hay confianza :D . Por otro lado, Dec en su truco 346 (http://www.clubdelphi.com/trucos/index.php?id=346) utiliza un TIdMultiPartFormDataStream, en concreto el método AddFormField para pasar los parámetros, ignoro cual es la mejor forma de hacerlo. A mi también se me hace mas cómodo usar un TStringList, en eso parece que estamos de acuerdo.

Por si tienes curiosidad wininet creo también maneja el código código 302, al menos maneja el 301 :) . En cuanto a las cookies, ya dije antes que si las maneja, incluso utiliza las cookies guardadas previamente, con el típico "Recordar contraseña" que se encuentra en algunas paginas web.

Pero dejemos este tema a un lado, lo importante es que tanto por un método como por el otro obtenemos un resultado en un Stream. Centremonos entonces en ese punto, yo también estoy esperando haber que solución se puede utilizar para examinar el contenido de la respuesta.

Al González
04-11-2006, 19:18:28
¡Hola de nuevo!

Muchas de estas cosas son nuevas para mí. Mi conocimiento actual sobre HTTP se reduce a unas pequeñas prácticas realizadas con PHP en el verano de 2005.

Con un día de retraso en mi agenda, empezaré a probar el componente TIdHttp, muy bien sugerido e ilustrado por David.

Domingo: los enlaces y ejemplos que me indicas me resultaron muy interesantes también. Ya había buscado en los foros, aunque no lo suficiente por lo que veo. :o

Antonio: habré de molestarte con algunos consejillos cuando me tope con eso de las galletas de sesión (¡mmm, galletas! :rolleyes:, de pronto abrírseme el apetito, me acercaré unas con chispas de chocolate que tengo en la cocina...:p).

Bien, manos a la obra...:cool:

Un abrazo HTTP.

Al González. :)

Al González
04-11-2006, 21:43:04
¡Hola a todos!

Ya le eché un vistazo superficial a las propiedades y eventos del componente TIdHTTP. Aquí el curso de mi pensamiento durante dicha labor:

--------------------------------------------------------------------------
Estudio del componente TIdHTTP.
Monólogo de acercamiento inicial.
Por Al González.

¡Vaya! Así que estos son los famosos Indy. Pero qué iconos tan simplones tienen, hasta un gatito aparece ahí...ah no, el diccionario dice que se trata de un «roedor semejante a la ardilla».

Bien, ya agregué un TIdHTTP a mi forma. La primera propiedad que tiene es AllowCookies, y aparece marcada con True negrita, como si su valor predeterminado fuese False. Lo más probable es que no le hayan puesto la cláusula Default a su declaración...Efectivamente, Doychin Bondzhev olvidó hacerlo, o no quiso. Prosigamos...

Curiosa nota en los comentarios de la unidad IdHTTP.pas:

Initially only GET and POST will be supported. As time goes on more will be added…

Sería interesante saber qué otros métodos de envío de datos pueden o podrían implementarse en HTTP.

AuthRetries. Ésta se me hace que la voy a necesitar para el ingreso de usuarios.

CookieManager. Aquí está la propiedad que decía Antonio. Por el momento voy a probar sin control de galletas (porque de hecho ya me las terminé :D).

HandleRedirects. Esto me suena a cuando quiero entrar a una página y el navegador me lleva a otra, a veces de forma temporal para decirme que he ganado 50 millones de dólares y churradas similares.

HTTPOptions. Amo las propiedades Options, tienen un no sé qué que siempre te saca de apuros. :) hoForceEncodeParams está en True, como debe ser; ya había olvidado que en las URLs deben codificarse los caracteres no ingleses para que cualquier servidor Web lo interprete correctamente (ojalá Unicode no pase a la historia como el Esperanto de las comunicaciones, urge su uso difundido).

MaxLineAction, MaxLineLength con valor default de 16384. No dudo que todavía haya programadores que se jactan de su ingenio escribiendo doscientas sentencias en una sola línea.

Port 80. Según he escuchado, el puerto que utilizan los navegadores. Bien.

ProtocolVersion con valor de pv1_1. Ahora que recuerdo, cuando estuve trabajando con un mecanismo de inserción automática de texto HTML en Word, la cabecera del texto llevaba algo de versión al principio. Y si mal no recuerdo, para compatibilidad, la versión usada era la 0.9 (o algo así). Me pregunto si tiene que ver una cosa con la otra y cómo influye esto de la versión en TIdHTTP.

Vaya, la ayuda dice «specifies the HTTP version used for Get, Head, and Post methods for the HTTP client». Entonces sí existen otros métodos (por lo menos uno) además de Get y Post, ¿cómo será eso del método Head?

ProxyParams. ¡Oh-oh! Creo que ha llegado la hora de investigar qué es exactamente un proxy (durante años sólo he tenido la vaga idea de que es una especie de filtro repartidor de Internet, y que por lo regular limita la libertad de los usuarios para no dejarlos trabajar a gusto). A ver Wikipedia, dime quién es el más bonito, digo, dime qué es un proxy. Bien, por lo que veo no estaba tan lejos, es un software (por lo general) que administra, controla y facilita automáticamente los accesos a Internet en una red.

Si el cliente tiene un proxy, supongo tendré que emplear las sub propiedades ProxyUsername y ProxyPassword. Algo a tener en cuenta.

ReadTimeout. Ha de ser el tiempo de espera para recibir una respuesta del servidor Web, aunque la ayuda dice que es «peer connection». Supongo que en este caso el término conexión se refiere a cada orden o submit, enviado al servidor Web, no a la sesión en sí.

Request. «Specifies the header values to send to the HTTP server… Use Response to examine header values received in an HTTP protocol response from the server». Y veo que Response («Specifies the header values received from the HTTP server») es otra propiedad pero no publicada sino pública. Es lógico, puesto que no tendría sentido que apareciese en el inspector de objetos.

Estas dos propiedades me despiertan varias dudas: ¿qué es eso de los valores de cabecera? ¿se referirá a lo del método Head que leí antes? ¿qué utilidad tiene? ¿cómo funciona? Tal vez Dec o Domingo lo sepan, qué chévere es contar con ellos :). ¿No tendrán otra cosa que hacer? Siempre están dando respuestas, y bastante buenas, son casi genios.

Tag. Seguro esta propiedad se refiere a las pestañas del navegador Mozilla. ¡Jejeje! es una broma que me hago a mí mismo.

Ahora pasemos al ver los eventos del componente...

Me llaman la atención los cuatro últimos, OnStatus, OnWork (vaya nombre menos descriptivo), OnWorkBegin y OnWorkEnd. Me pregunto qué utilidad tienen. Ah, vaya, el primero como que sirve para saber en qué parte del proceso se encuentra la petición al servidor Web. Los OnWorkXXX no me quedan claros, leeré de nuevo la ayuda; interesante: «OnWork is generally used to control the update of progress indicators or GUI components», dice algo similar para los otros dos.

OK, ya le eché un vistazo general a las propiedades y eventos del componente TIdHTTP. Ahora voy a hacer mi primera prueba (¡qué emoción!). Por lo pronto quisiera empezar con una página distinta a la que requiero acceder con mi aplicación. ¿Qué página estará buena para hacer esta prueba? ¿www.ponchito.com, www.youtube.com?..., ¡ah, ya sé! https://login.yahoo.com/config/mail?.intl=us con una cuenta temporal. Con tu permiso Yahoo...
--------------------------------------------------------------------------

De antemano, gracias por auxiliarme con mis dudas :o. Seguiremos informando. :cool:

Un abrazo índyco.

Al González. :)

seoane
04-11-2006, 22:25:04
Vamos a ver si te puedo explicar algunas cosas, al menos como yo las recuerdo de cuando me ley el protocolo para hacer mi pico servidor :D . Espero no equivocarme mucho ...


Vaya, la ayuda dice «specifies the HTTP version used for Get, Head, and Post methods for the HTTP client». Entonces sí existen otros métodos (por lo menos uno) además de Get y Post, ¿cómo será eso del método Head?


Es verdad, el protocolo http tiene varios comandos los habituales Get y Post, y algunos otros. Ahora mismo solo me acuerdo del Head y el Connect, pero creo que algún otro hay. El Head básicamente es similar al Get solo que el servidor al responder solo devuelve las cabeceras y no el resto de la respuesta, esto puede ser practico, por ejemplo, si queremos obtener información sobre un archivo, como si esta disponible o cuantos bytes ocupa sin tener que descargarlo. El connect se utiliza para establecer túneles a través de los proxys para las conexiones seguras, pero eso ya es otra historia. Hablando de cabeceras ...


Estas dos propiedades me despiertan varias dudas: ¿qué es eso de los valores de cabecera? ¿se referirá a lo del método Head que leí antes? ¿qué utilidad tiene? ¿cómo funciona?


En el protocolo http tanto las peticiones (Request) como respuestas (Response) tienen un formato similar. Se dividen en una serie de cabeceras, una linea para cada una y el propio cuerpo del mensaje. Separados por una linea en blanco. Un ejemplo:

Petición de la pagina de google:

GET / HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, */*
Accept-Language: es
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Host: www.google.es
Proxy-Connection: Keep-Alive



Se puede ver que la primera linea es el comando (Get,Head,Post,etc), las otras cabeceras dan otra información como el Host, el tipo de navegador, etc. Fíjate en la linea en blanco al final, esta indica el final de las cabeceras y el comiendo de los datos, como es un comando get no hay datos, si fuera un comando Post la información se enviaría a continuación de la linea en blanco.

Y que es lo que nos responde google:

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Server: GWS/2.1
Content-Length: 4289
Date: Sat, 04 Nov 2006 21:01:23 GMT

{A partir de aqui nos manda el documento no lo pongo porque aqui se veria mal}

La primera linea nos indica el código de la respuesta 200 para OK, 404 para no encontrado, 302 para dirigirnos a otro lado, etc ... Las otras nos indican el tipo de documento que nos manda o la longitud, entre otras cosas.

Ahora vamos con otras preguntas que hiciste:

AuthRetries. Ésta se me hace que la voy a necesitar para el ingreso de usuarios.

El protocolo http cuenta con un sistema de autenticación muy básico, que codifica la contraseña en base64. Quizá lo habrás visto alguna vez al intentar entrar en una pagina protegida muestra un dialogo para introducir el nombre de usuario y contraseña. Este sistema se uso mucho, aunque ahora la mayoría de las paginas utilizan su propio sistema de autenticación contra una base de datos usando un formulario y por ejemplo php, quedando este sistema bastante en desuso. Si la pagina a la que quieres entrar usan un formulario lo mas seguro es que no use este método de autenticación.


HandleRedirects. Esto me suena a cuando quiero entrar a una página y el navegador me lleva a otra, a veces de forma temporal para decirme que he ganado 50 millones de dólares y churradas similares.


Esto hace que si recibe como respuesta códigos como el 302 pidiendo que se dirija a otra dirección le haga caso y vaya, como ya dijo roman esto puede ser necesario para entrar en alguna pagina.

Bueno, creo que ya llego por ahora, aunque si tienes duda por algo o quieres meterte mas en profundidad en algún tema, tu solo dilo ;) Porque ya sabes "que no tengo otra cosa que hacer" :D

seoane
05-11-2006, 22:59:26
Bueno, mientras no me aclaro con las "Expresiones regulares" sigo haciendo pruebas usando la función Pos de toda la vida :D . Aquí os dejo un juguetito, que se conecta al club delphi con tu nombre de usuario y contraseña, y comprueba si tienes mensajes sin leer. Puedes indicarle que haga la comprobación automáticamente cada 5 minutos y te avise con un pitido si hay mensaje nuevos. Para que esto funcione después de leer los mensajes hay que usar la opción de los foros "Marcar Foros Como Leídos", o de lo contrario seguirá viendolos como mensajes nuevos.

Lo dicho, es solo un juguete, para entretenerse mientras no nos metemos mas a fondo en el tema. Espero que este hilo no decaiga ...

Al González
05-11-2006, 23:47:00
¡Hola a todos!

Gracias por esa herramienta Domingo. Será muy interesante echarle un vistazo. :)

Actualizo el caso:

--------------------------------------------------------------------------
Prueba del componente TIdHTTP
Informe #1

Cargué en un navegador la página dada por la URL https://login.yahoo.com/config/mail?.intl=us, la cual es el punto de entrada al correo electrónico de Yahoo para cuentas de Estados Unidos. Esta página solicita los típicos nombre de usuario y contraseña de cualquier sistema de correo. Tomé su código fuente HTML guardándolo localmente como CorreoYahoo.htm. Al explorar su contenido con el bloc de notas, encontré que, como habría de esperarse, el método de envío de datos que utiliza es el Post:

<form method="post"...

Como ya sabemos, cuando el método es Get, los datos de captura son enviados al servidor Web como parte de la cadena URL; mientras que con el método Post, los datos son enviados de forma interna o “no visible”.

Me despertó curiosidad el saber cómo se comportaría la página y el servidor de Yahoo, si cambiara la palabra post por get. Lo hice y guardé el archivo como CorreoYahooGet.htm. Al ejecutar esa página Web, capturando la clave de usuario y contraseña que solicita, vi como estos dos datos aparecieron, junto con otros valores, en la barra de direcciones del navegador (como parámetros en la URL), lo cual era de esperarse. Lo interesante fue ver que el sistema de corro de Yahoo permitió el ingreso, a pesar de haber enviado los datos de esta manera.

Me llamó la atención otro detalle de la línea

<form method="post" action="https://login.yahoo.com/config/login?"

Entiendo que el atributo Action de la etiqueta Form indica la URL que el sistema deberá ejecutar al someter (submit) los datos, y que el signo de interrogación (“?”) se utiliza para dar inicio a los parámetros enviados en la misma URL cuando se utiliza el método Get. Mi pregunta entonces es ¿por qué aparece ahí el signo de interrogación si el método que utiliza la página es Post y no Get?

Sobre el útilmente sobrecargado método TIdHTTP.Post, la documentación dice algo que me pareció lógico y a la vez interesante:

When ASource is a TStrings instance, Post will replace all occurrences of
the End-Of-Line (EOL) character in ASource with the value '&' prior to
transfer to the HTTP server. When ASource is a TStream instance, no
preprocessing of the stream content is performed.

El símbolo ampersand (“&”) se utiliza para separar los parámetros entre sí en la URL cuando se utiliza el método Get. Es útil que cuando los parámetros son proporcionados como una lista TStrings, el método Post haga la sustitución de saltos de línea por dicho símbolo. Cuando los parámetros son indicados mediante un flujo TStream, éste es tomado tal cual esté, por lo que deberá contener ya los separadores & que sean necesarios.

De ahí que Tefots, incluya tales símbolos en el ejemplo que tan amablemente nos proporciona en el mensaje 12. Pero coincido con Román en que resulta más práctico usar una lista TStrings (el método TIdHTTP.Post también acepta ese formato). Por cierto, recuerdo haber visto un par de muy acertadas intervenciones de Román en este hilo, pero ya no están aquí. ¿Alguna razón especial por la que hayan desaparecido?

El siguiente es el código fuente de la prueba inicial:


procedure TForm1.Button1Click(Sender: TObject);
Var
Parametros :TStringList;
begin
Parametros := TStringList.Create;

Try
Parametros.Add ('login=debefuncionar');
Parametros.Add ('passwd=xxxxxxxxxxxxx');

Try
Memo1.Text := IdHTTP1.Post ('https://login.yahoo.com/config/login?',
Parametros);
Except
On E :Exception Do
ShowMessage (E.Message);
End;
Finally
Parametros.Free;
End;
end;


La llamada al método IdHTTP1.Post me arroja una excepción EIdIOHandlerPropInvalid con el mensaje «IOHandler value is not valid».

Debe considerarse lo siguiente:

La URL comienza con https y no http. Cuando el protocolo es HTTPS, el componente TIdHTTP exige el uso de un componente adicional TIdSSLIOHandlerSocket asignado a su propiedad IOHandler, como puede observarse en este extracto del código de IDHTTP.pas (Delphi 7):


if AnsiSameText(URL.Protocol, 'HTTPS') then
begin
// Just check can we do SSL
if not Assigned(IOHandler) or (not (IOHandler is TIdSSLIOHandlerSocket)) then
raise EIdIOHandlerPropInvalid.Create(RSIOHandlerPropInvalid)


Esto es algo importante a considerar, ahora que suelen verse en la Red muchos sitios que son «https://…».

Para cumplir con este requisito, hago uso de un componente TIdSSLIOHandlerSocket. Aún cuando los sitios a los que deseo acceder después de este aprendizaje sean de protocolo HTTP y no HTTPS, me interesa lograr hacer pruebas exitosas con HTTPS también. Aclaro que la excepción elevada que menciono ocurre por otras causas.

Depurando paso a paso el código de las unidades involucradas (con la opción Use Debug DCUs, que permite que uno pueda meterse hasta la cocina), encontré que la causa de este error se origina en el hecho de que la función Load de la unidad IdSSLOpenSSLHeaders.pas no logra cargar correctamente algunas DLLs.

Según este enlace de Borland:
http://support.borland.com/entry.jspa?categoryID=150&externalID=406, se requiere un software llamado OpenSSL, específicamente los archivos libeay32.dll y ssleay32.dll para poder usar los componentes Indy con SSL (Secure Socket Layer), que es la especificación utilizada por una página HTTPS.

El sitio oficial de OpenSSL es http://www.openssl.org/, sin embargo no encontré en él un instalador que proporcione de manera fácil las dos DLLs que necesito. Así que descargué OpenSSL 0.9.8d para Win32 del sitio http://www.slproweb.com/products/Win32OpenSSL.html y lo instalé.

Pero aún así la excepción mencionada sigue apareciendo al intentar hacer la llamada al método Post. Haciendo un examen más minucioso de la citada función Load, descubrí que las DLLs sí logran cargarse, más no las funciones IdSslCtxSetInfoCallback, IdSslX509StoreCtxGetAppData, IdSslSessionGetId, IdSslSessionGetIdCtx, IdSslCtxGetVersion, IdSslCtxSetOptions, IdSslX509GetNotBefore, IdSslX509GetNotAfter, iddes_set_odd_parity, iddes_set_key e iddes_ecb_encrypt, que probablemente pertenecen a esas DLLs.

Ante esto, sospecho que debo utilizar otra versión de OpenSSL (no la 0.9.8d) para conseguir que tales funciones se carguen correctamente y con ello poder utilizar el componente TIdHTTP con sitios que utilizan Secure Socket Layer (HTTPS).
--------------------------------------------------------------------------

Les agradezo de antemano su ayuda.

Un abrazo neófito.

Al González. :)

seoane
06-11-2006, 00:00:48
Por cierto, recuerdo haber visto un par de muy acertadas intervenciones de Román en este hilo, pero ya no están aquí. ¿Alguna razón especial por la que hayan desaparecido?


A mi también me parecieron muy interesantes los argumentos de Roman. :confused: ¿Que habrá pasado?

dec
06-11-2006, 04:09:16
Hola,


Me llamó la atención otro detalle de la línea

<form method="post" action="https://login.yahoo.com/config/login?"

Entiendo que el atributo Action de la etiqueta Form indica la URL que el sistema deberá ejecutar al someter (submit) los datos, y que el signo de interrogación (“?”) se utiliza para dar inicio a los parámetros enviados en la misma URL cuando se utiliza el método Get. Mi pregunta entonces es ¿por qué aparece ahí el signo de interrogación si el método que utiliza la página es Post y no Get?


No debes preocuparte. El signo de interrogación no hace nada, simplemente, en este caso. Es posible que Yahoo! tenga algún sistema (entre otros muchos) que se encarge de construir las URLs (hablo para entendernos) y, sencillamente, dicho sistema añada las variables que sean necesarias en la URL... y si no encuentra variables que agregar no lo hace, pero, deja en la URL ese signo de interrogación seguido del cual irían las variables. En este caso no le des más vueltas: lo mismo da un "action" que el otro:


<form method="post" action="https://login.yahoo.com/config/login?"

// Es lo mismo que

<form method="post" action="https://login.yahoo.com/config/login"



Ante esto, sospecho que debo utilizar otra versión de OpenSSL (no la 0.9.8d) para conseguir que tales funciones se carguen correctamente y con ello poder utilizar el componente TIdHTTP con sitios que utilizan Secure Socket Layer (HTTPS).


Lo que puedo decir es que hace un tiempito me puse a escribir a modo de prueba un cliente de correo (muy sui generis) que se conectaba a GMail y descargaba los nuevos correos de determinadas cuentas de usuario. Hube de usar las librerías que mencionas con los componentes de Indy y, bueno, todo fue bastante bien. De hecho son librerías que usan no pocos programas para bregar con el protocolo SSL, como bien dices.

Al González
06-11-2006, 17:02:00
¡Hola a todos!

...Espero que este hilo no decaiga ...
Yo espero lo mismo. :)

...Hube de usar las librerías que mencionas con los componentes de Indy y, bueno, todo fue bastante bien. De hecho son librerías que usan no pocos programas para bregar con el protocolo SSL, como bien dices.
Que bien. ¿Podrías decirme qué versiones de Delphi y OpenSSL utilizaste? :)

Gracias.

Al González. :)

dec
08-11-2006, 01:21:54
Hola,

Casi se me pasa responder a esto Al, te pido disculpas. Yo utilizé la última versión de ambos "programas", es decir, la última versión de las librerías que pude conseguir y a la vez la versión 10 de los componentes Indy. De echo hace poco probé el programa que escribí a modo de ejemplo y traté de hacerlo funcionar con Indy 9 y no pude hacerlo. Lo digo para que conste. Con Delphi 10 y lo que yo recuerdo son la última versión de OpenSSL pude hacer lo que quería: conectar con Gmail y traer los nuevos correos de varias cuentas. ;)

Crandel
15-12-2006, 02:34:43
Aquí os dejo un juguetito, que se conecta al club delphi con tu nombre de usuario y contraseña, y comprueba si tienes mensajes sin leer.

Al fin me he dignado a usar tu código de acceso a paginas web con WinInet y he mirado el código del programa que escribiste.

He visto que repites varias veces la sentencia:
FreeAndNil(Respuesta);
Respuesta:= TStringStream.Create('');

Se reemplazar por esta para que quede mejor:
Respuesta.Size := 0;

seoane
15-12-2006, 02:45:05
Muy cierto Crandel, es mejor poner la propiedad size a cero. Por cierto, no comentas que te parece el resto del código.

PD: Aprovecho para preguntar ¿que le paso a este hilo? ¿se puede considerar muerto? ¿nadie mas saco algo en limpio?

Al González
15-12-2006, 06:46:55
¡Hola a todos!

...Aprovecho para preguntar ¿que le paso a este hilo? ¿se puede considerar muerto? ¿nadie mas saco algo en limpio?...
Hace unos minutos me dije: «voy a revisar el correo mientras Pepe realiza esas últimas pruebas» y entonces descubro esta pregunta de Domingo.

Mañana instalaremos la primera versión de la solución a nuestro cliente. Ya es funcional la automatización sobre dos de los tres sitios Web (en una versión básica). Faltará hacer algunas mejoras, pero confío en que pronto tendremos esto al 100%.

Algunos datos clave para quienes deseen desarrollar este tipo de soluciones:

El componente TIdHTTP es excelente, pero no es la única herramienta que utilizamos. En cada caso primero hay que estudiar las tripas del sitio Web, elaborando un "mapa" de las URLs que se mandan llamar y sus parámetros. Un largo trabajo de arqueología informática, donde se requiere mucha paciencia. En este punto, mi recomendación es usar un componente TWebBrowser para saber cuáles son los parámetros que la página envía al servidor Web, y entonces después poder automatizar esos envíos con TIdHTTP. Domingo Seoane nos expone un buen ejemplo del evento TWebBrowser.OnBeforeNavigate2 en este mensaje (http://www.clubdelphi.com/foros/showpost.php?p=162388&postcount=3).

(la sentencia "ShowMessage(Values['P1']);" puede ser sustituida por "ShowMessage(Text);" para mostrar todos los parámetros (nombres y valores) que están a punto de enviarse en la petición).

Gracias Domingo, ese ejemplo me sirvió muchísimo cuando no encontraba la manera de ver los parámetros que una página enviaba bajo el método Post. Lo que usualmente hacía para averiguarlo era guardar una copia local de la página como archivo .htm, cambiar su método Post por Get y ejecutar tal archivo, pero por alguna razón no se guardaba correctamente (incluso hasta instalé Firefox por primera vez para intentarlo con ese otro navegador :D). Pero definitivamente es más profesional hacer trabajo de arqueología con herramientas más finas y no puro pico y pala. :p

La esencia de automatizar un sitio Web ya sea con TIdHTTP o con rutinas de más bajo (y flexible) nivel como las propuestas por Domingo, consiste en conocer las URLs (direcciones Web) a las cuales hay que ordenarles algo y los parámetros que habremos de enviarles para que ese algo ocurra de manera correcta. Dichas URLs aparecen en los atributos "Action" de las etiquetas HTML "Forms" (¿cómo? ¿el lector todavía no ha usado la opción "Ver código fuente" de su navegador? :confused:).

Generalmente, cuando se invoca a una de esas direcciones Web, el misterioso programa servidor que se encuentra del otro lado de la línea (generalmente Apache), nos envía como respuesta un flujo de bytes HTML, una página vaya. El resto del trabajo consiste en analizar ese flujo de bytes como una cadena de caracteres, buscando en posiciones específicas el dato que deseamos extraer.

Esto no quiere decir que vamos a estudiar la cadena que regresó byte por byte. La cadena de bytes puede ser guardada como una página .htm y verla con mayor detalle en cualquier editor de texto. De hecho esto se hace generalmente desde antes de empezar a programar (me meto al navegador, consulto un dato y la página que me regresa la guardo como archivo local). Se estudia ese archivo de texto para encontrar patrones comunes que ayuden a identificar con seguridad la posición donde siempre aparece el dato que buscamos. Es decir, ya se ha familiarizado uno con el código fuente de una página de resultados y es entonces cuando podemos escribir un algoritmo que acaricie a esos caracteres y bese a la parte más sensible de la cadena, obteniendo ese «¡Si, aquí!» que todos deseamos escuchar. ;)


{ Primera fila de datos es el último producto consultado de la
cotización }
I := Pos ('dp[1]=new Prt(', Respuesta);

If I = 0 Then
Exit;

Contador := 0;

For I := I + 14 To MaxInt Do
If Respuesta [I] = ',' Then
Begin
Inc (Contador);

{ Después de la tercera coma está el valor para el parámetro "whs"
usado en la consulta de disponibilidad }
If Contador = 3 Then
Begin
ParametroWhs := Copy (Respuesta, I + 2,
PosEx ('''', Respuesta, I + 2) - (I + 2));
End
Else
{ Después de la octava coma está el precio }
If Contador = 8 Then
Begin
Precio := ValorNumerico (Copy (Respuesta, I + 2,
PosEx ('''', Respuesta, I + 2) - (I + 2)));
End
Else
{ Después de la vigésima coma está el valor para el parámetro
"invtid" usado en la consulta de disponibilidad }
If Contador = 20 Then
Begin
ParametroInvtid := Copy (Respuesta, I + 2,
PosEx ('''', Respuesta, I + 2) - (I + 2));
Break;
End;
End;


En las próximas versiones vamos a utilizar alguna biblioteca (esas que creíamos que eran librerías en el siglo pasado) especial para análisis sintáctico HTML y reconocimiento de expresiones regulares. Esto con el fin de hacer más segura la extracción de datos. Porque como el propietario del sitio cambie ligeramente el diseño de la página...¡pabernosmatao! :eek:

Todo esto que escribí fue a botepronto (palabra hermana de pabernosmatao) y en base a mis escasos conocimientos sobre la Web. Aún así, espero que resulte de utilidad y de antemano pido disculpas por si dije alguna babosada.

Ahora sí me voy a cenar, mañana será al gran día (a ver cómo me sale la quincena :rolleyes:).

Un abrazo parseado.

Crandel
15-12-2006, 11:33:24
Muy cierto Crandel, es mejor poner la propiedad size a cero. Por cierto, no comentas que te parece el resto del código.

Por un lado te comento que tu función SendRequest funciona de maravillas, yo estaba implementando mi programa con TidHttp y tenia problemas que no me guardaba la sesión de conexión, entonces cuando una vez me autentificaba y luego pedia otra página que necesitara parametros (signo ? despues de la dirección de la página) ya me pedia que me registre de nuevo.

Ahora lo implemente con SendRequest y no tengo ese problema, en realidad se adapta mejor a mi problema porque realmente simula que es el IE y no un programa de automatización :D

Por otro lado estoy usando una clase llamada THTMLParser para analizar el texto de las paginas web con buenos resultados, ya me pondre mas a delante a estudiar "Expresiones regulares" que parece ser una mejor herramienta.

Roger007
16-12-2006, 15:25:37
Viendo todo esto: ¿Se podria ejecutar un navegar pasandole los parametros necesarios para el login?

Ejemplo:


WinExec('C:\Archivos de programa\Internet Explorer\iexplore.exe http://clubdelphi/foros/login.php vb_login_username=usuario vb_login_password=password s= do=login',1);


O algo asi, para que habra el navegador con la web del foro y ya logeado con mi usuario y password.

Un saludo, Roger.

Crandel
16-12-2006, 16:08:59
Lo que puedes hacer, es usar la función SendRequest de seoane con la que te logueas, y luego envias la orden que se habra la pagina que quieras con el IE sin necesidad de mandar parámetros.

No lo he probado pero deberia funcionar.

seoane
16-12-2006, 16:20:30
Viendo todo esto: ¿Se podria ejecutar un navegar pasandole los parametros necesarios para el login?


Pues no lo he probado, pero pasarle los parámetros por Get no es lo mismo que pasarle los parámetros por Post. Si el diseñador de la pagina ha tenido en cuenta la posibilidad de pasar lo parámetros por Get, puede que funcione, aunque lo mas seguro es que no.


Lo que puedes hacer, es usar la función SendRequest de seoane con la que te logueas, y luego envias la orden que se habra la pagina que quieras con el IE sin necesidad de mandar parámetros.


No creo que eso funcione, cuando nos logueamos con mi función recibimos un identificador de sesión, un identificador que solo es valido dentro de nuestra aplicación. Así que si abrimos el explorador, este estará dentro de una sesión nueva, a menos que seamos capaces de enviarle de alguna manera el valor de la cookie de sesión, aunque lo veo difícil.

Lo que si podríamos hacer en el caso del ClubDelphi, es loguearnos usando la función SendRequest, pero marcando la opción "Recuerdame", de esta forma la información de login se guardara en una cookie persistente que la nueva ventana del explorer si podrá utilizar.

Al González
27-12-2006, 04:54:31
¡Hola a todos!

Los saludo con muchísimo gusto esperando que hayan tenido una muy feliz Navidad y deseándoles lo mejor para el año que está por comenzar.

Les actualizo mi caso, ahora si estoy en algunos aprietos técnicos. :(

Son dos problemas en sí:

1. En una de las páginas que estoy automatizando veo que los parámetro enviados mediante el método Post son:


----------------------------7d6242382036e
Content-Disposition:
form-data;
name="equipmentData"
-1
-----------------------------7d6242382036e
Content-Disposition:
form-data;
name="serialNumber"
-----------------------------7d6242382036e
Content-Disposition:
form-data;
name="consumptionCountryAnswer"
Y
-----------------------------7d6242382036e
Content-Disposition:
form-data;
name="filetogo1";
filename=""
Content-Type:
application/octet-stream


Observen que el signo de igual separa el nombre de los parámetros de sus valores. ¿Cómo es posible que uno de los parámetros se llame "----------------------------7d6242382036e
Content-Disposition:
form-data;
name"? :confused:

Al parecer están codificados (encriptados). Como pista, se supone que esos parámetros incluyen las cadenas "6D1948", "3F5108" y "8D3902", ya que las capturo en tres cuadros de texto de la página Web antes de hacer el "sumbit". Pero no encuentro aún la relación entre un "----------------------------7d6242382036e" y un 6D1948, aunque sospecho que no es tan difícil de averiguar. :rolleyes:


2. El otro problema que tengo es que el sitio Web es HTTPS por lo que tengo que usar las DLLs libeay32.dll y ssleay32.dll, pero aún así, el componente TIdHTTP me arroja la excepción: EIdOSSLConnectError with message 'Error connecting with SSL. En este momento no puedo determinar que versión de SSL estoy usando, pero ¿cuál versión me sugieren utilizar con Delphi 7 y dónde podría conseguir ese par de DLLs?

De antemano les agradezco su ayuda.

Un abrazo espacial.

Al González. :)

seoane
27-12-2006, 14:04:20
Hola Al,

Lo que planteas tiene una explicación muy sencilla. La codificación del formulario es diferente a la que estas acostumbrado. Hasta ahora habías tratado con formularios cuyo atributo enctype era "aplicación/x-www-form-urlencoded", por lo que los datos del formulario tenían un aspecto como este:

nombre1=valor1&nombre2=valor2


Ahora parece ser que el formulario usa "multipart/form-data". Este es otro tipo de codificación distinta, que se suele usar cuando además de texto, se necesita mandar otro tipo de información, como por ejemplo archivos. Una explicación un poco mas detallada la puedes encontrar aqui (http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4) o puedes leer la normativa rfc2045 (http://www.ietf.org/rfc/rfc2045.txt) :D

Con relación a tu pregunta, "----------------------------7d6242382036e" no es mas que un separador y no tiene relación con el valor de ninguno de los parámetros.

Creo que Indy puede trabajar con este tipo de codificación, pero ya sabes que yo soy mas de WinInet, así que es mejor que alguien con mas experiencia en Indy te lo confirme.

Crandel
28-12-2006, 00:58:30
Lo que si podríamos hacer en el caso del ClubDelphi, es loguearnos usando la función SendRequest, pero marcando la opción "Recuerdame", de esta forma la información de login se guardara en una cookie persistente que la nueva ventana del explorer si podrá utilizar.

Veamos, estoy conectado a un sitio que utiliza cookies para el acceso, por eso puedo abrir varias veces el IE y seguir usandolo como el mismo usuario.

Lo mismo lo estoy con mi programa, el problema es que ahora quiero abrir varias instancias de mi programa, pero que cada una este conectada con un usuario diferente. El sitio me obliga a usar cookies.

pd: Estoy usando WinInet

Al González
28-12-2006, 19:53:53
¡Hola a todos!

...La codificación del formulario es diferente a la que estas acostumbrado. Hasta ahora habías tratado con formularios cuyo atributo enctype era "aplicación/x-www-form-urlencoded", por lo que los datos del formulario tenían un aspecto como este:

nombre1=valor1&nombre2=valor2


Ahora parece ser que el formulario usa "multipart/form-data". Este es otro tipo de codificación distinta, que se suele usar cuando además de texto, se necesita mandar otro tipo de información...
Gracias por la información Domingo. Ante esta eventualidad vi conveniente abrir otro hilo para tratar de forma más específica el problema:

TWebBrowser y TIdHTTP con “multipart/form-data”, ¿se puede? (http://www.clubdelphi.com/foros/showthread.php?t=38791)

De antemano gracias.

Un abrazo multiparte.

Al González. :)

roman
10-02-2007, 02:06:06
2. El otro problema que tengo es que el sitio Web es HTTPS por lo que tengo que usar las DLLs libeay32.dll y ssleay32.dll, pero aún así, el componente TIdHTTP me arroja la excepción: EIdOSSLConnectError with message 'Error connecting with SSL. En este momento no puedo determinar que versión de SSL estoy usando, pero ¿cuál versión me sugieren utilizar con Delphi 7 y dónde podría conseguir ese par de DLLs?


No sé si se resolvió esto. Yo acabo de tener que enfrentarme con ello y luego de múltiples intentos pude hacerlo así:


Usando las dlls de http://indy.fulgan.com/SSL/, la m (http://indy.fulgan.com/SSL/indy_OpenSSL096m.zip) para ser más exacto.

Conectando un IdSSLIOHandlerSocketOpenSSL a la propiedad IOHandler del IdHTTP

En la propiedad SSLOptions.Method de IdSSLIOHandlerSocketOpenSSL puse cualquier valor excepto el que trae por defecto


Todo esto con Indy 10 y mediante el método científico de probar una por una las opciones hasta dar con la adecuada :)

// Saludos

Al González
18-02-2007, 04:27:24
¡Hola a todos!

Antes que nada pido una disculpa por demorarme más de un mes en retomar el tema. Román: felicidades por la nueva marca ;) y gracias por los datos que proporcionas sobre Indy.

Me parece que uno de los problemas residía en que estaba yo utilizando la versión 9 de esta biblioteca de componentes, en lugar de la 10 (nunca la he actualizado):

gsIdVersion = '9.00.10';

Aunque por el momento no he comprobado si esa era la causa del conflicto.

Debido a que también había que resolver el otro problema (cómo enviar datos multi parte), y ya no contaba con mucho tiempo para investigar más por mi cuenta, decidí confiar esta última pieza del caso a un colega de Veracruz, quien finalmente tuvo más éxito que yo, pero utilizando un componente de Kyriacos Michael llamado TIEHTTP (http://www.badfan.com/delphi/tie_http_https.html), el cual viene con un buen soporte para envío de datos multipart. El único detalle en contra de este componente es que requiere Internet Explorer, pero en el caso concreto que nos ocupa acá eso no representa ningún problema.

Ya se está utilizando aceptablemente la versión preliminar de la aplicación, pero ahora tengo en mente hacer esto con muli hilo (multithread), lo cual desconozco si es soportado por TIdHTTP y TIEHTTP (ojalá que sí). La idea es que mientras el servidor Web responde a una consulta, pueda lanzarse otra más, ya sea al mismo servidor Web o a otro (la aplicación hace múltiples consultas a tres servidores, la idea es que ahora las haga de manera simultánea para economizar tiempo). Haré algunas pruebas y les avisaré lo que ocurra.

De antemano les agradezco por cualquier consejo que consideren útil.

Un abrazo múltiple.

Al González. :)

Crandel
11-03-2007, 23:48:59
cuando nos logueamos con mi función recibimos un identificador de sesión, un identificador que solo es valido dentro de nuestra aplicación. Así que si abrimos el explorador, este estará dentro de una sesión nueva, a menos que seamos capaces de enviarle de alguna manera el valor de la cookie de sesión

Hola Seoane, podrias especificar dentro de tu función cual es el identificador de session del que hablas.

Estoy realizando la conexion a un servidor con multihilo, pero el resto de los hilos pierden la sesion, como hago para que todos mantengan la misma sesion?

edito: me parece que mi problema esta por otro lado, no esta perdiendo la sesion, porque un hilo si lo esta manteniendo.

jobequ
12-02-2008, 18:04:50
Buenas tardes.. Amigos soy nuevo en este sitio y para serles sincero no creo tener ni la mitad del conocimiento q tienen ustedes y por eso les pido su ayuda.. Resulta que aqui en venezuela para poder solicitar la cita del pasaporte es necesario ingresar a esta pag: http://www.onidex.com.ve/ pero el servicio brindado por esta pagina es fatal, osea no sirve.. (NO PUEDO CONECTARME CON FACILIDAD) El servicio de la pagina es todo el dia pero las solicitudes se acaban en menos de media hora a partir de las 9 am. Lo que quisiera yo es q me ayuden a poder automatizar la entrada a la pagina sin tener que estar dandole reintentar todo el tiempo y tambien a poder llenar todo lo q pide la pag de forma automatica con agun programa o algo.. Les repito no se mucho en relacion a esto pero puedo aprender.. Espero pronta respuesta y de antemano muchas gracias.. (Para su mayor comodidad puenen in gresar a la pag despues de las 11 am hora venezuela)

hach
13-02-2008, 22:14:03
Hola Al
como dec, yo accedo a Gmail con indy y tambien tuve problemas con las versiones de libeay32.dll y ssleay32.dll
No recuerdo como pero logre dar con las versiones indicadas
uso delphi 7 con las indy que el trae... que versión serán? parece que 9.00.10
las versiones de dll que me funcionan son las de indy_OpenSSL096m
Si no las consigues te las paso

Saludos

Pablo

hach
13-02-2008, 22:16:47
Perdón, me pasa por apurado y no leer todo!!!
Ya estaba resuelto este tema...
Muy interesante el hilo!!!!!
Saludos otra vez

Pablo

djemix
27-09-2010, 18:36:22
Hola chicos!!!

Perdón por reabrir este antiguo hilo, pero la verdad es que me ha venido genial el trabajo realizado por todos.

Pero me surge una duda/cuestión, a ver si saben como atacarla. ¿Como realizo las llamadas a las funciones Javascript que contiene la web solicitada?

Un saludo!!

jachguate
29-09-2010, 01:23:52
No existe tal cosa como "llamadas a las funciones Javascript".

Y pues... qué hacer dependería de lo que queres lograr. Si lo que queres es, por ejemplo, imitar una llamada al servidor (típico ajax), lo que toca es "armar" una llamada identica a la que generaría el javascript y lanzarla desde Delphi.

Por el contrario, si el javascript modifica elementos del DOM, pues tocaría primero interpretar el HTML para tener una estructura similar en memoria y luego utilizar, por ejemplo, algún interprete de javascript para delphi que le permita a dicho "script" interactuar con el DOM que vos mismo has armado...

En fin... la pregunta es demasiado general como para darte una respuesta más cercana a una solución.

Hasta luego.

djemix
29-09-2010, 09:01:44
Claro... El tema es que es Ajax lo que quiero realizar, pero el problema es que la funcion Javascript que quiero lanzar no viene en el fuente de la web y no sé qué hace realmente.
Entiendo que tendría que capturar la llamada a la página php y ver los parametros tanto en get como en post que le pasa no?

calcena
09-12-2010, 10:40:48
buenas, he visto que hay programadores que extraen datos de una web, para mi programa me seria necesrio extraer datos de una web descargada en .txt pero con tango TAGS no tengo ni flores de como hacerlo.
Gracias a todos por vuestras ideas.

jachguate
10-12-2010, 23:34:02
Si sabes que es lo que buscas, tan sencillo como hacer una llamada a la función Pos para identificar donde inicia/termina la información que te interesa.

Si no, el camino a seguir podría ser el uso de un parser html para delphi (http://www.google.com.gt/search?q=delphi+html+parser) que interprete los tags y te devuelva, ya sea mediante eventos o una estructura en memoria información sobre sus hallazgos. Todo depende de lo que queres hacer....

Un saludo.

pedrolazarus
04-05-2013, 02:46:58
Bueno, como alternativa a Indy podemos usar Wininet. Podemos hacer Get, podemos hacer Post y maneja las cookies perfectamente incluso las de sesión. No tengo nada en contra de las Indy, es solo por dar alternativas, además no se pueden usar en el Turbo :mad: , aunque eso no es culpa suya.

Bueno, un poco de código para animar la cosa:




Y se formo la fiesta:D

Exelente aporte para lo que no tienen instalado el componente indy sobre todo en lazarus

obelixxx
02-07-2017, 04:33:07
disculpen si toco el tema de mucho tiempo.. es que me parece un tema estupendo y que me ha servido de mucho.


Bueno, me puse a usar el TIEHTTP. y lamentablemente ya no tiene soporte que yo sepa...

y recien me a tocado enfrentarme al protocolo "HTTPS"

queria saber si el creador del tema resolvio el acceso a paginas con HTTPS usando el TIEHTTP


vi que se discute sobre soluciones usando las INDY y el Idhttps y unas dlls. lo que pasa es que tengo ya decenas de programas escritos con TIEHTTP y queria saber si por ese lado se puede acceder a usar el protocolo HTTPS, si alguien sabe algo le agradezco de antemano una ayuda.

saludos y exitos.