zoukankan      html  css  js  c++  java
  • delphi idhttp 实战用法(TIdhttpEx)

    以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


    复制代码
    1 unit uIdHttpEx;
    2
    3 interface
    4
    5 uses
    6 Classes, Idhttp, uIdCookieMgr, IdSSLOpenSSL;
    7 {uIdCookieMgr 是我改进的}
    8
    9 type
    10
    11 TIdhttpEx = class(TIdhttp)
    12 private
    13 FIdCookieMgr: TIdCookieMgr;
    14 FIdSSL: TIdSSLIOHandlerSocketOpenSSL;
    15 public
    16 constructor Create(AOwner: TComponent);
    17 property CookieMgr: TIdCookieMgr read FIdCookieMgr;
    18 procedure GenRandomUserAgent; //随便生成一个请求头,可以忽略或自己改进
    19 property IdSSL: TIdSSLIOHandlerSocketOpenSSL read FIdSSL;
    20
    21 end;
    22
    23 implementation
    24
    25 { TIdhttpEx }
    26
    27 const
    28
    29 sUserAgent =
    30 '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)';
    31 // sAccept = 'image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, */*';
    32 sUserAgent2 =
    33 '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)';
    34 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, */*';
    35
    36 sUserAgent3 =
    37 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36';
    38 sAccept2 = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';
    39
    40 MaxUserAgentCount = 3;
    41
    42 var
    43 UserAgent: array [0 .. MaxUserAgentCount - 1] of string;
    44
    45 constructor TIdhttpEx.Create(AOwner: TComponent);
    46 begin
    47 inherited;
    48
    49 HTTPOptions := []; // 禁止POST参数编码,自己手动编 HttpEncodeX
    50
    51 // HTTPOptions := [hoNoParseMetaHTTPEquiv]; // 禁止POST参数编码,自己手动编 HttpEncodeX
    52 // hoNoParseMetaHTTPEquiv 禁止解析html 此可能造成假死!
    53
    54 FIdCookieMgr := TIdCookieMgr.Create(self);
    55 CookieManager := FIdCookieMgr;
    56
    57 // ssl 需要 libeay32.dll ssleay32.dll 阿里旺旺目录下可以搜索到
    58
    59 FIdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(self);
    60 IOHandler := FIdSSL;
    61
    62 HandleRedirects := true;
    63 AllowCookies := true;
    64 ProtocolVersion := pv1_1;
    65
    66 Request.RawHeaders.FoldLength := 25000; // 参数头长度,重要
    67
    68 ReadTimeout := 15000;
    69 ConnectTimeout := 15000;
    70
    71 RedirectMaximum := 5;
    72 Request.UserAgent := sUserAgent3;
    73 Request.Accept := sAccept;
    74 Request.AcceptEncoding := 'gzip';
    75
    76 end;
    77
    78 procedure TIdhttpEx.GenRandomUserAgent;
    79 begin
    80 Randomize;
    81 self.Request.UserAgent := UserAgent[Random(MaxUserAgentCount)];
    82 end;
    83
    84 initialization
    85
    86 UserAgent[0] :=
    87 '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)';
    88 UserAgent[1] :=
    89 '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)';
    90 UserAgent[2] :=
    91 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36';
    92
    93 // 这三句请忽略,有些网站认求头,我随便写的。请大家根本实际情况改进
    94 finalization
    95
    96 end.
    复制代码
    uIdCookieMgr.Pas


    复制代码
    1 unit uIdCookieMgr;
    2
    3 interface
    4
    5 uses
    6 IdCookieManager, Classes;
    7
    8 type
    9 TIdCookieMgr = class(TIdCookieManager)
    10 private
    11
    12 procedure SetCurCookies(const Value: string);
    13
    14 function GetCurCookies: string;
    15 function GetCookieList: TStringList;
    16
    17 public
    18
    19 procedure SaveCookies(const AFileName: string);
    20 procedure LoadCookies(const AFileName: string);
    21
    22 function GetCookieValue(const ACookieName: string): string;
    23 property CurCookies: string read GetCurCookies write SetCurCookies;
    24
    25 end;
    26
    27 implementation
    28
    29 uses
    30 IdCookie, SysUtils, IdURI, uStrUtils, IdGlobalProtocols, DateUtils;
    31 { uStrUtils 一套操作字串的函数单元 }
    32
    33 function TIdCookieMgr.GetCookieList: TStringList;
    34 var
    35 C: Tcollectionitem;
    36 begin
    37 result := TStringList.Create;
    38 for C in CookieCollection do
    39 result.add((C as TIdCookie).CookieText);
    40 end;
    41
    42 function TIdCookieMgr.GetCookieValue(const ACookieName: string): string;
    43 var
    44 n: integer;
    45 begin
    46 result := '';
    47 if IsNotEmptyStr(ACookieName) then
    48 begin
    49 n := CookieCollection.GetCookieIndex(ACookieName);
    50 if n >= 0 then
    51 result := CookieCollection.Cookies[n].Value;
    52 end;
    53 end;
    54
    55 function TIdCookieMgr.GetCurCookies: string;
    56 var
    57 strs: TStringList;
    58 begin
    59 strs := GetCookieList;
    60 try
    61 result := strs.Text;
    62 finally
    63 strs.Free;
    64 end;
    65 end;
    66
    67 procedure TIdCookieMgr.LoadCookies(const AFileName: string);
    68 var
    69 StrLst: TStringList;
    70 C: TIdCookie;
    71 uri: TIdURI;
    72 s, t: string;
    73 begin
    74 StrLst := TStringList.Create;
    75 uri := TIdURI.Create;
    76 try
    77 if FileExists(AFileName) then
    78 begin
    79 StrLst.LoadFromFile(AFileName);
    80 for s in StrLst do
    81 begin
    82 C := CookieCollection.add;
    83 CookieCollection.AddCookie(C, uri);
    84 C.ParseServerCookie(s, uri);
    85 C.Domain := GetStrBetween(s, 'Domain=', ';');
    86 C.Path := GetStrBetween(s, 'Path=', ';');
    87 t := GetStrBetween(s, 'Expires=', 'GMT') + 'GMT'; // GetStrBetween 在 uStrUtils 单元中
    88 C.Expires := CookieStrToLocalDateTime(t);
    89 end;
    90 end;
    91 finally
    92 uri.Free;
    93 StrLst.Free;
    94 end;
    95 end;
    96
    97 procedure TIdCookieMgr.SaveCookies(const AFileName: string);
    98 var
    99 StrLst: TStringList;
    100 begin
    101 StrLst := GetCookieList;
    102 try
    103 StrLst.SaveToFile(AFileName);
    104 finally
    105 StrLst.Free;
    106 end;
    107 end;
    108
    109 procedure TIdCookieMgr.SetCurCookies(const Value: string);
    110 var
    111 StrLst: TStringList;
    112 C: TIdCookie;
    113 uri: TIdURI;
    114 s, t: string;
    115 begin
    116 StrLst := TStringList.Create;
    117 uri := TIdURI.Create;
    118 try
    119 StrLst.Text := Value;
    120 CookieCollection.Clear;
    121 for s in StrLst do
    122 begin
    123 C := CookieCollection.add;
    124 CookieCollection.AddCookie(C, uri);
    125 C.ParseServerCookie(s, uri);
    126 C.Domain := GetStrBetween(s, 'Domain=', ';');
    127 C.Path := GetStrBetween(s, 'Path=', ';');
    128 t := GetStrBetween(s, 'Expires=', 'GMT') + 'GMT';
    129 C.Expires := CookieStrToLocalDateTime(t);
    130 end;
    131 finally
    132 uri.Free;
    133 StrLst.Free;
    134 end;
    135 end;
    136
    137 end.
    复制代码
    uOperateIndy.pas 非常有用操作 TIdhttpEx 全靠它了


    复制代码
    1 unit uOperateIndy;
    2
    3 interface
    4
    5 uses
    6 Classes, Idhttp, IdMultipartFormData;
    7
    8 function IdhttpGet(AIdhttp: TIdHTTP; AUrl: string; var AHtml: string): Boolean;
    9 function IdhttpPost(AIdhttp: TIdHTTP; AStrList: TStringList; AUrl: string; var AHtml: String)
    10 : Boolean; overload;
    11 function IdhttpPost(AIdhttp: TIdHTTP; AIdMul: TIdMultiPartFormDataStream; AUrl: string;
    12 var AHtml: string): Boolean; overload;
    13
    14 function GetHtmlFromUrl(AUrl: string; var AHtml: string): Boolean;
    15
    16 implementation
    17
    18 uses
    19 uIdhttpEx, SysUtils, ZLibEx, StrUtils, uStrUtils, uHtmlElement, uParseHtml;
    20 { 带u的单元,都是我写的,ZLibEx 是解压库 }
    21
    22 //解压GZIP 那个参数31是试出来的
    23 procedure DecompressGZIP(inStream, outStream: TStream); inline;
    24 begin
    25 ZDecompressStream2(inStream, outStream, 31);
    26 end;
    27
    28 function HtmlIsUTF8(AHtml: string): Boolean;
    29 var
    30 BMetaList: TSingleHtmlElementList;
    31 BMeta: TSingleHtmlElement;
    32 BKeyElement: PKeyElement;
    33 BCheckOver: Boolean;
    34 sKeyName: string;
    35 sKeyValue: string;
    36 begin
    37 Result := false;
    38 BMetaList := TSingleHtmlElementList.Create;
    39 try
    40
    41 GetMetaList(AHtml, BMetaList);
    42
    43 BCheckOver := false;
    44
    45 for BMeta in BMetaList do
    46 begin
    47
    48 for BKeyElement in BMeta.KeyElementList do
    49 begin
    50
    51 sKeyName := UpperCase(BKeyElement.Name);
    52 sKeyValue := UpperCase(BKeyElement.Value);
    53
    54 if PosEx('UTF-8', sKeyValue) > 0 then
    55 begin
    56 Result := true;
    57 BCheckOver := true;
    58 break;
    59 end;
    60
    61 end;
    62
    63 if BCheckOver then
    64 break;
    65 end;
    66
    67 finally
    68 BMetaList.Free;
    69 end;
    70 end;
    71
    72 function GetHtmlAfterOperateIdhttp(AIdhttp: TIdHTTP; AStream: TStream): string;
    73 var
    74 BSize: Int64;
    75 BOutStream: TMemoryStream;
    76 TempStream: TMemoryStream;
    77 rS: RawByteString;
    78 s: string;
    79 sUtf8: string;
    80 BIsUtf8: Boolean;
    81 sCharSet: string;
    82
    83 begin
    84 BSize := AStream.Size;
    85
    86 BOutStream := TMemoryStream.Create;
    87 try
    88 if BSize > 0 then
    89 begin
    90
    91 if PosEx('GZIP', UpperCase(AIdhttp.Response.ContentEncoding)) > 0 then
    92 begin
    93 AStream.Position := 0;
    94 DecompressGZIP(AStream, BOutStream);
    95 TempStream := BOutStream;
    96 end
    97 else
    98 TempStream := TMemoryStream(AStream);
    99
    100 BSize := TempStream.Size;
    101 SetLength(rS, BSize);
    102 TempStream.Position := 0;
    103 TempStream.ReadBuffer(rS[1], BSize);
    104
    105 s := string(rS);
    106 sUtf8 := UTF8ToString(rS);
    107
    108 sCharSet := AIdhttp.Response.CharSet;
    109 BIsUtf8 := PosEx('UTF-8', UpperCase(sCharSet)) > 0;
    110 if not BIsUtf8 then
    111 BIsUtf8 := HtmlIsUTF8(s);
    112
    113 if BIsUtf8 then
    114 Result := sUtf8
    115 else
    116 begin
    117
    118 if (PosEx('的', sUtf8) > 0) or (PosEx('地', sUtf8) > 0) or (PosEx('为', sUtf8) > 0) or
    119 (PosEx('于', sUtf8) > 0) or (PosEx('我们', sUtf8) > 0) or (PosEx('电', sUtf8) > 0) or
    120 (PosEx('邮', sUtf8) > 0) then
    121
    122 begin
    123 Result := sUtf8;
    124 end
    125 else
    126 Result := s;
    127
    128 end;
    129
    130 end
    131 finally
    132 BOutStream.Free;
    133 end;
    134
    135 end;
    136
    137 function IdhttpGet(AIdhttp: TIdHTTP; AUrl: string; var AHtml: string): Boolean;
    138 var
    139 BStrStream: TMemoryStream;
    140 begin
    141 AHtml := '';
    142 BStrStream := TMemoryStream.Create;
    143 try
    144 try
    145 AIdhttp.Get(AUrl, BStrStream);
    146 AHtml := GetHtmlAfterOperateIdhttp(AIdhttp, BStrStream);
    147 Result := true;
    148 except
    149 on e: Exception do
    150 begin
    151 Result := false;
    152 AHtml := e.Message;
    153 end;
    154 end;
    155 finally
    156 BStrStream.Free;
    157 end;
    158 end;
    159
    160 function IdhttpPost(AIdhttp: TIdHTTP; AStrList: TStringList; AUrl: string; var AHtml: String)
    161 : Boolean; overload;
    162 var
    163 BStrStream: TMemoryStream;
    164 begin
    165 Result := true;
    166 AHtml := '';
    167 BStrStream := TMemoryStream.Create;
    168 try
    169 try
    170 AIdhttp.Post(AUrl, AStrList, BStrStream);
    171 AHtml := GetHtmlAfterOperateIdhttp(AIdhttp, BStrStream);
    172 except
    173 on e: Exception do
    174 begin
    175 AHtml := e.Message;
    176 Result := false;
    177 end;
    178 end;
    179 finally
    180 BStrStream.Free;
    181 end;
    182 end;
    183
    184 function IdhttpPost(AIdhttp: TIdHTTP; AIdMul: TIdMultiPartFormDataStream; AUrl: string;
    185 var AHtml: string): Boolean; overload;
    186 var
    187 BStrStream: TMemoryStream;
    188 begin
    189 Result := true;
    190 AHtml := '';
    191 BStrStream := TMemoryStream.Create;
    192 try
    193 try
    194 AIdhttp.Post(AUrl, AIdMul, BStrStream);
    195 AHtml := GetHtmlAfterOperateIdhttp(AIdhttp, BStrStream);
    196 except
    197 on e: Exception do
    198 begin
    199 AHtml := e.Message;
    200 Result := false;
    201 end;
    202 end;
    203 finally
    204 BStrStream.Free;
    205 end;
    206 end;
    207
    208 function GetHtmlFromUrl(AUrl: string; var AHtml: string): Boolean;
    209 var
    210 Idhttp: TIdhttpEx;
    211 begin
    212 Idhttp := TIdhttpEx.Create(nil);
    213 try
    214 Result := IdhttpGet(Idhttp, AUrl, AHtml);
    215 finally
    216 Idhttp.Free;
    217 end;
    218 end;
    219
    220 end.
    复制代码
    附:delphi 进阶基础技能说明

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

  • 相关阅读:
    Windows平台下的读写锁
    进程的阻塞和挂起的区别
    事件函数SetEvent、PulseEvent与WaitForSingleObject详解
    多线程的那点儿事(之多线程调试)
    多线程同步内功心法——PV操作上(未完待续。。。)
    读者写者问题(有bug 后续更改)
    解决VS2010控制台程序运行结束不显示请按任意键继续
    Method has too many Body parameters openfeign
    Eclipse中Cannot nest src folder解决方法
    restTemplate重定向问题 &cookie问题
  • 原文地址:https://www.cnblogs.com/findumars/p/7019722.html
Copyright © 2011-2022 走看看