以delphi XE8 自带indy(10.5.8.0)组件为例,分享实战中遇到的问题及解决方法。

TIdHttpEx 用法实例01[多线程获取网页](包含完整源码)

实例02(如何Post参数,如何保存与提取Cookie)待写

TIdHttpEx 已实现了对GZIP的解压,对UTF-8编码解码等

本文包含以下几个单元

uIdhttp.pas (TIdHttpEx)

uIdCookieMgr.pas (TIdCookieMgr)

uOperateIndy.pas 操作 TIdhttpEx 全靠它了

uIdhttp.Pas

unit uIdHttpEx;

interface

uses
Classes, Idhttp, uIdCookieMgr, IdSSLOpenSSL;
{uIdCookieMgr 是我改进的} type TIdhttpEx = class(TIdhttp)
private
FIdCookieMgr: TIdCookieMgr;
FIdSSL: TIdSSLIOHandlerSocketOpenSSL;
public
constructor Create(AOwner: TComponent);
property CookieMgr: TIdCookieMgr read FIdCookieMgr;
procedure GenRandomUserAgent; //随便生成一个请求头,可以忽略或自己改进
property IdSSL: TIdSSLIOHandlerSocketOpenSSL read FIdSSL; end; implementation { TIdhttpEx } const sUserAgent =
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 2.0.50727)';
// sAccept = 'image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, */*';
sUserAgent2 =
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.3; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)';
sAccept = 'application/x-shockwave-flash, image/gif, image/jpeg, image/pjpeg, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*'; sUserAgent3 =
'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36';
sAccept2 = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'; MaxUserAgentCount = ; var
UserAgent: array [ .. MaxUserAgentCount - ] of string; constructor TIdhttpEx.Create(AOwner: TComponent);
begin
inherited; HTTPOptions := []; // 禁止POST参数编码,自己手动编 HttpEncodeX // HTTPOptions := [hoNoParseMetaHTTPEquiv]; // 禁止POST参数编码,自己手动编 HttpEncodeX
// hoNoParseMetaHTTPEquiv 禁止解析html 此可能造成假死! FIdCookieMgr := TIdCookieMgr.Create(self);
CookieManager := FIdCookieMgr; // ssl 需要 libeay32.dll ssleay32.dll 阿里旺旺目录下可以搜索到 FIdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(self);
IOHandler := FIdSSL; HandleRedirects := true;
AllowCookies := true;
ProtocolVersion := pv1_; Request.RawHeaders.FoldLength := ; // 参数头长度,重要 ReadTimeout := ;
ConnectTimeout := ; RedirectMaximum := ;
Request.UserAgent := sUserAgent3;
Request.Accept := sAccept;
Request.AcceptEncoding := 'gzip'; end; procedure TIdhttpEx.GenRandomUserAgent;
begin
Randomize;
self.Request.UserAgent := UserAgent[Random(MaxUserAgentCount)];
end; initialization UserAgent[] :=
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 2.0.50727)';
UserAgent[] :=
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.3; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)';
UserAgent[] :=
'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36'; // 这三句请忽略,有些网站认求头,我随便写的。请大家根本实际情况改进
finalization end. uIdhttpEx.pas

uIdCookieMgr.Pas

unit uIdCookieMgr;

interface

uses
IdCookieManager, Classes; type
TIdCookieMgr = class(TIdCookieManager)
private procedure SetCurCookies(const Value: string); function GetCurCookies: string;
function GetCookieList: TStringList; public procedure SaveCookies(const AFileName: string);
procedure LoadCookies(const AFileName: string); function GetCookieValue(const ACookieName: string): string;
property CurCookies: string read GetCurCookies write SetCurCookies; end; implementation uses
IdCookie, SysUtils, IdURI, uStrUtils, IdGlobalProtocols, DateUtils;
{ uStrUtils 一套操作字串的函数单元 } function TIdCookieMgr.GetCookieList: TStringList;
var
C: Tcollectionitem;
begin
result := TStringList.Create;
for C in CookieCollection do
result.add((C as TIdCookie).CookieText);
end; function TIdCookieMgr.GetCookieValue(const ACookieName: string): string;
var
n: integer;
begin
result := '';
if IsNotEmptyStr(ACookieName) then
begin
n := CookieCollection.GetCookieIndex(ACookieName);
if n >= then
result := CookieCollection.Cookies[n].Value;
end;
end; function TIdCookieMgr.GetCurCookies: string;
var
strs: TStringList;
begin
strs := GetCookieList;
try
result := strs.Text;
finally
strs.Free;
end;
end; procedure TIdCookieMgr.LoadCookies(const AFileName: string);
var
StrLst: TStringList;
C: TIdCookie;
uri: TIdURI;
s, t: string;
begin
StrLst := TStringList.Create;
uri := TIdURI.Create;
try
if FileExists(AFileName) then
begin
StrLst.LoadFromFile(AFileName);
for s in StrLst do
begin
C := CookieCollection.add;
CookieCollection.AddCookie(C, uri);
C.ParseServerCookie(s, uri);
C.Domain := GetStrBetween(s, 'Domain=', ';');
C.Path := GetStrBetween(s, 'Path=', ';');
t := GetStrBetween(s, 'Expires=', 'GMT') + 'GMT'; // GetStrBetween 在 uStrUtils 单元中
C.Expires := CookieStrToLocalDateTime(t);
end;
end;
finally
uri.Free;
StrLst.Free;
end;
end; procedure TIdCookieMgr.SaveCookies(const AFileName: string);
var
StrLst: TStringList;
begin
StrLst := GetCookieList;
try
StrLst.SaveToFile(AFileName);
finally
StrLst.Free;
end;
end; procedure TIdCookieMgr.SetCurCookies(const Value: string);
var
StrLst: TStringList;
C: TIdCookie;
uri: TIdURI;
s, t: string;
begin
StrLst := TStringList.Create;
uri := TIdURI.Create;
try
StrLst.Text := Value;
CookieCollection.Clear;
for s in StrLst do
begin
C := CookieCollection.add;
CookieCollection.AddCookie(C, uri);
C.ParseServerCookie(s, uri);
C.Domain := GetStrBetween(s, 'Domain=', ';');
C.Path := GetStrBetween(s, 'Path=', ';');
t := GetStrBetween(s, 'Expires=', 'GMT') + 'GMT';
C.Expires := CookieStrToLocalDateTime(t);
end;
finally
uri.Free;
StrLst.Free;
end;
end; end. uIdCookeMgr.pas

uOperateIndy.pas 非常有用操作 TIdhttpEx 全靠它了

unit uOperateIndy;

interface

uses
Classes, Idhttp, IdMultipartFormData; function IdhttpGet(AIdhttp: TIdHTTP; AUrl: string; var AHtml: string): Boolean;
function IdhttpPost(AIdhttp: TIdHTTP; AStrList: TStringList; AUrl: string; var AHtml: String)
: Boolean; overload;
function IdhttpPost(AIdhttp: TIdHTTP; AIdMul: TIdMultiPartFormDataStream; AUrl: string;
var AHtml: string): Boolean; overload; function GetHtmlFromUrl(AUrl: string; var AHtml: string): Boolean; implementation uses
uIdhttpEx, SysUtils, ZLibEx, StrUtils, uStrUtils, uHtmlElement, uParseHtml;
{ 带u的单元,都是我写的,ZLibEx 是解压库 } //解压GZIP 那个参数31是试出来的
procedure DecompressGZIP(inStream, outStream: TStream); inline;
begin
ZDecompressStream2(inStream, outStream, );
end; function HtmlIsUTF8(AHtml: string): Boolean;
var
BMetaList: TSingleHtmlElementList;
BMeta: TSingleHtmlElement;
BKeyElement: PKeyElement;
BCheckOver: Boolean;
sKeyName: string;
sKeyValue: string;
begin
Result := false;
BMetaList := TSingleHtmlElementList.Create;
try GetMetaList(AHtml, BMetaList); BCheckOver := false; for BMeta in BMetaList do
begin for BKeyElement in BMeta.KeyElementList do
begin sKeyName := UpperCase(BKeyElement.Name);
sKeyValue := UpperCase(BKeyElement.Value); if PosEx('UTF-8', sKeyValue) > then
begin
Result := true;
BCheckOver := true;
break;
end; end; if BCheckOver then
break;
end; finally
BMetaList.Free;
end;
end; function GetHtmlAfterOperateIdhttp(AIdhttp: TIdHTTP; AStream: TStream): string;
var
BSize: Int64;
BOutStream: TMemoryStream;
TempStream: TMemoryStream;
rS: RawByteString;
s: string;
sUtf8: string;
BIsUtf8: Boolean;
sCharSet: string; begin
BSize := AStream.Size; BOutStream := TMemoryStream.Create;
try
if BSize > then
begin if PosEx('GZIP', UpperCase(AIdhttp.Response.ContentEncoding)) > then
begin
AStream.Position := ;
DecompressGZIP(AStream, BOutStream);
TempStream := BOutStream;
end
else
TempStream := TMemoryStream(AStream); BSize := TempStream.Size;
SetLength(rS, BSize);
TempStream.Position := ;
TempStream.ReadBuffer(rS[], BSize); s := string(rS);
sUtf8 := UTF8ToString(rS); sCharSet := AIdhttp.Response.CharSet;
BIsUtf8 := PosEx('UTF-8', UpperCase(sCharSet)) > ;
if not BIsUtf8 then
BIsUtf8 := HtmlIsUTF8(s); if BIsUtf8 then
Result := sUtf8
else
begin if (PosEx('的', sUtf8) > ) or (PosEx('地', sUtf8) > ) or (PosEx('为', sUtf8) > ) or
(PosEx('于', sUtf8) > ) or (PosEx('我们', sUtf8) > ) or (PosEx('电', sUtf8) > ) or
(PosEx('邮', sUtf8) > ) then begin
Result := sUtf8;
end
else
Result := s; end; end
finally
BOutStream.Free;
end; end; function IdhttpGet(AIdhttp: TIdHTTP; AUrl: string; var AHtml: string): Boolean;
var
BStrStream: TMemoryStream;
begin
AHtml := '';
BStrStream := TMemoryStream.Create;
try
try
AIdhttp.Get(AUrl, BStrStream);
AHtml := GetHtmlAfterOperateIdhttp(AIdhttp, BStrStream);
Result := true;
except
on e: Exception do
begin
Result := false;
AHtml := e.Message;
end;
end;
finally
BStrStream.Free;
end;
end; function IdhttpPost(AIdhttp: TIdHTTP; AStrList: TStringList; AUrl: string; var AHtml: String)
: Boolean; overload;
var
BStrStream: TMemoryStream;
begin
Result := true;
AHtml := '';
BStrStream := TMemoryStream.Create;
try
try
AIdhttp.Post(AUrl, AStrList, BStrStream);
AHtml := GetHtmlAfterOperateIdhttp(AIdhttp, BStrStream);
except
on e: Exception do
begin
AHtml := e.Message;
Result := false;
end;
end;
finally
BStrStream.Free;
end;
end; function IdhttpPost(AIdhttp: TIdHTTP; AIdMul: TIdMultiPartFormDataStream; AUrl: string;
var AHtml: string): Boolean; overload;
var
BStrStream: TMemoryStream;
begin
Result := true;
AHtml := '';
BStrStream := TMemoryStream.Create;
try
try
AIdhttp.Post(AUrl, AIdMul, BStrStream);
AHtml := GetHtmlAfterOperateIdhttp(AIdhttp, BStrStream);
except
on e: Exception do
begin
AHtml := e.Message;
Result := false;
end;
end;
finally
BStrStream.Free;
end;
end; function GetHtmlFromUrl(AUrl: string; var AHtml: string): Boolean;
var
Idhttp: TIdhttpEx;
begin
Idhttp := TIdhttpEx.Create(nil);
try
Result := IdhttpGet(Idhttp, AUrl, AHtml);
finally
Idhttp.Free;
end;
end; end. uOperateIndy.pas

http://www.cnblogs.com/lackey/p/4085131.html

delphi idhttp 实战用法(TIdhttpEx)的更多相关文章

  1. (转载)Delphi TStringList的用法

    Delphi TStringList的用法 TStrings是一个抽象类,在实际开发中,是除了基本类型外,应用得最多的. TStringList 常用方法与属性: var List: TStringL ...

  2. Delphi TStringList的用法

    Delphi TStringList的用法 TStrings是一个抽象类,在实际开发中,是除了基本类型外,应用得最多的. TStringList 常用方法与属性: var List: TStringL ...

  3. Delphi Inputbox,InputQuery用法

    Delphi :InputQuery,InputBox用法及区别 function InputQuery(const ACaption, APrompt: string; var Value: str ...

  4. Delphi IDHTTP控件:GET/POST 请求

    Delphi IDHTTP控件:GET/POST 请求   最近一直在使用IDHTTP,下面是一些关于 GET.POST 请求基本使用方法的代码 一.GET 请求 1 procedure GetDem ...

  5. Delphi XE4 TStringHelper用法详解

    原文地址:Delphi XE4 TStringHelper用法详解作者:天下为公 Delphi XE4的TStringHelper,对操作字符串进一步带来更多的方法,估计XE5还能继续用到. Syst ...

  6. (转)sudo配置文件/etc/sudoers详解及实战用法

    sudo配置文件/etc/sudoers详解及实战用法 原文:http://blog.csdn.net/field_yang/article/details/51547804 一.sudo执行命令的流 ...

  7. delphi FillChar的用法(转)

    delphi FillChar的用法(转) (2012-12-24 15:12:06) 转载▼ 标签: it 分类: delphi7 FillChar的用法(delphi) Fillchar是Turb ...

  8. Delphi IdHttp组件+IdHttpServer组件实现文件下载服务

     http://blog.csdn.net/xxkku521/article/details/16864759 Delphi IdHttp组件+IdHttpServer组件实现文件下载服务 2013- ...

  9. Delphi IDHTTP用法详解(六种用法)

    一.IDHTTP的基本用法 IDHttp和WebBrowser一样,都可以实现抓取远端网页的功能,但是http方式更快.更节约资源,缺点是需要手动维护cook,连接等 IDHttp的创建,需要引入ID ...

随机推荐

  1. jQuery的入门与简介《思维导图》

    <初学者请各位高手指点指点> jQuery是继Prototype之后又一个优秀的JavaScript库,在JavaScript基础上我知道了jQuery拥有强大的选择器, 出色的DOM操作 ...

  2. linux查看CPU高速缓存(cache)信息

    一.Linux下查看CPU Cache级数,每级大小 dmesg | grep cache 实例结果如下: 二.查看Cache的关联方式 在 /sys/devices/system/cpu/中查看相应 ...

  3. 【转】Android LCD(一):LCD基本原理篇

    关键词:android LCD TFT 液晶 偏光片 彩色滤光片  背光 平台信息:内核:linux2.6/linux3.0系统:android/android4.0 平台:samsung exyno ...

  4. js点击事件防止用户重复点击执行

    点击事件里给button标签加一个自定义属性,存上次点击时间 追问: 求详细代码,JS 真心的没怎么做过 追答:   <input type="button" id=&quo ...

  5. Unity 集成联通SDK

    我相信Unity程序员都会遇到加入SDK的问题,我相信如果你不会android编程,我相信你的CPU当场计算过快而爆炸!  这里也写笔记希望能帮助大家 如果有讲错的地方,希望大家能回复并且提供答案!  ...

  6. IOS 计算密码强度

    + (BOOL) judgeRange:(NSArray*)conditionArr Password:(NSString*)password { NSRange range; BOOL result ...

  7. JDK5新特性之线程同步集合(五)

    一. 传统集合: 传统方式下的Collection在迭代集合时, 不同意对集合进行改动: public class CollectionModifyExceptionTest { public sta ...

  8. Linux-0.11内核源代码分析系列:内存管理get_free_page()函数分析

    Linux-0.11内存管理模块是源码中比較难以理解的部分,如今把笔者个人的理解发表 先发Linux-0.11内核内存管理get_free_page()函数分析 有时间再写其它函数或者文件的:) /* ...

  9. js执行环境深入研究

    js 声明函数是创建函数对象的过程,当创建函数对象时,函数对象的[[scope]] =连当前执行环境对象的作用域(栈顶执行环境--当执行函数时,js会将该函数的执行环境对象入栈) 当为全局函数时,如: ...

  10. ueditor+asp.net异步提交,可以实现了,嘿嘿

    之前没用过Ueditor去异步提交,最近项目需要用到这个,就下了个来用,结果可能没仔细去看Ueditor的相关介绍文档,然后自己也郁闷了一下才把它弄出来,现在可以实现异步提交了,松口气,把代码贴出来, ...