火车采集器软件交流官方论坛

 找回密码
 加入会员
搜索
火车采集器V9版免费下载火车浏览器 - 可视采集,万能群发,全自动脚本工具
楼主: faunus

采集原理(不要跟贴,谢谢。)

[复制链接]
 楼主| 发表于 2008-10-24 15:28:33 | 显示全部楼层

文件下载

 楼主| 发表于 2008-10-24 20:36:56 | 显示全部楼层

验证码

图片验证码的类

修改说明: 
1,对源代码做了部分算法优化;
2,对图像输出做了优化;
3,对图像的反识别做了优化;
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Drawing;

namespace Common
{
    
///&#160;<summary>
&#160;&#160;&#160;&#160;
///&#160;验证码模块
&#160;&#160;&#160;&#160;
///&#160;</summary>

&#160;&#160;&#160;&#160;public&#160;class&#160;CreateImage
&#160;&#160;&#160;&#160;
{
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
public&#160;static&#160;void&#160;DrawImage()
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
{
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;HttpContext.Current.Response.Clear();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CreateImage&#160;img&#160;
=&#160;new&#160;CreateImage();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;HttpContext.Current.Session[
"CheckCode"]&#160;=&#160;img.RndNum(3);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;img.CreateImages(HttpContext.Current.Session[
"CheckCode"].ToString());
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;HttpContext.Current.Response.End();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}


&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
///&#160;<summary>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
///&#160;生成验证图片
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
///&#160;</summary>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
///&#160;<param&#160;name="checkCode">验证字符</param>

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;private&#160;void&#160;CreateImages(string&#160;checkCode)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
{
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
int&#160;iwidth&#160;=&#160;(int)(checkCode.Length&#160;*&#160;13);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;System.Drawing.Bitmap&#160;image&#160;
=&#160;new&#160;System.Drawing.Bitmap(iwidth,&#160;20);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Graphics&#160;g&#160;
=&#160;Graphics.FromImage(image);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;g.Clear(Color.White);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
//定义颜色
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Color[]&#160;c&#160;=&#160;{&#160;Color.Black,&#160;Color.Red,&#160;Color.DarkBlue,&#160;Color.Green,&#160;Color.Orange,&#160;Color.Brown,&#160;Color.DarkCyan,&#160;Color.Purple&#160;};
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
//定义字体&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;string[]&#160;font&#160;=&#160;{&#160;"Verdana",&#160;"Microsoft&#160;Sans&#160;Serif",&#160;"Comic&#160;Sans&#160;MS",&#160;"Arial",&#160;"宋体"&#160;};
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Random&#160;rand&#160;
=&#160;new&#160;Random();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
//输出不同字体和颜色的验证码字符
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;for&#160;(int&#160;i&#160;=&#160;0;&#160;i&#160;<&#160;checkCode.Length;&#160;i++)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
{
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
int&#160;cindex&#160;=&#160;rand.Next(7);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
int&#160;findex&#160;=&#160;rand.Next(5);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Font&#160;f;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
int&#160;k=rand.Next(3);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
if&#160;(&#160;k==&#160;1){&#160;f&#160;=&#160;new&#160;System.Drawing.Font(font[findex],&#160;13,&#160;FontStyle.Bold);&#160;}
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
else&#160;if&#160;(k&#160;==&#160;2)&#160;{f&#160;=&#160;new&#160;System.Drawing.Font(font[findex],&#160;13,&#160;FontStyle.Bold&#160;|&#160;FontStyle.Strikeout);&#160;}
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
else&#160;{&#160;f&#160;=&#160;new&#160;System.Drawing.Font(font[findex],&#160;13,&#160;FontStyle.Bold&#160;|&#160;FontStyle.Italic);&#160;};
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Brush&#160;b&#160;
=&#160;new&#160;System.Drawing.SolidBrush(c[cindex]);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;g.DrawString(checkCode.Substring(i,&#160;
1),&#160;f,&#160;b,&#160;&#160;(i&#160;*&#160;12),&#160;rand.Next(2));
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
//画一个边框
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;g.DrawRectangle(new&#160;Pen(Color.Black,&#160;0),&#160;0,&#160;0,&#160;image.Width&#160;-&#160;1,&#160;image.Height&#160;-&#160;1);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
//随机输出噪点
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;for&#160;(int&#160;i&#160;=&#160;0;&#160;i&#160;<&#160;50;&#160;i++)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
{
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
int&#160;x&#160;=&#160;rand.Next(image.Width);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
int&#160;y&#160;=&#160;rand.Next(image.Height);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
float&#160;x1,&#160;y1;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;x1&#160;
=&#160;0.5F;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;y1&#160;
=&#160;0.5F;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;g.DrawRectangle(
new&#160;Pen(Color.LightGray,&#160;0),&#160;x,&#160;y,&#160;x1,&#160;y1);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
//输出到浏览器
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;HttpContext.Current.Response.ClearContent();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;HttpContext.Current.Response.ContentType&#160;
=&#160;"image/Jpeg";
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;image.Save(HttpContext.Current.Response.OutputStream,&#160;System.Drawing.Imaging.ImageFormat.Jpeg);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;g.Dispose();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;image.Dispose();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}


&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
///&#160;<summary>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
///&#160;生成随机的字母
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
///&#160;</summary>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
///&#160;<param&#160;name="VcodeNum">生成字母的个数</param>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
///&#160;<returns>string</returns>

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;private&#160;string&#160;RndNum(int&#160;VcodeNum)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
{
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
//采用一个简单的算法以保证生成随机数的不同
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Random&#160;rand&#160;=&#160;new&#160;Random();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
int&#160;min=(int)Math.Pow(10,&#160;VcodeNum);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
int&#160;max=(int)(Math.Pow(10,&#160;VcodeNum&#160;+&#160;1)&#160;-&#160;1);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
return&#160;rand.Next(min,&#160;max).ToString();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}

&#160;&#160;&#160;&#160;}



}


推荐一个图片验证码网站不错的。
http://www.lafdc.com/captcha/&#160;




[ 本帖最后由 faunus 于 2008-10-24 21:03 编辑 ]
 楼主| 发表于 2008-10-26 21:51:35 | 显示全部楼层
 楼主| 发表于 2008-10-27 20:09:31 | 显示全部楼层

BASE64

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,在发送电子邮件时,服务器认证的用户名和密码需要用Base64编码,附件也需要用Base64编码。
下面简单介绍Base64算法的原理,由于代码太长就不在此贴出
Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。

Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。

这样说会不会太抽象了?不怕,我们来看一个例子:

转换前        aaaaaabb        ccccdddd        eeffffff         
转换后        00aaaaaa        00bbcccc        00ddddee        00ffffff
应该很清楚了吧?上面的三个字节是原文,下面的四个字节是转换后的Base64编码,其前两位均为0。

转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),这个表是这样的:(摘自RFC2045)
                                 Table 1: The Base64 Alphabet

      Value Encoding  Value Encoding  Value Encoding  Value Encoding
           0 A            17 R            34 i            51 z
           1 B            18 S            35 j            52 0
           2 C            19 T            36 k            53 1
           3 D            20 U            37 l            54 2
           4 E            21 V            38 m            55 3
           5 F            22 W            39 n            56 4
           6 G            23 X            40 o            57 5
           7 H            24 Y            41 p            58 6
           8 I            25 Z            42 q            59 7
           9 J            26 a            43 r            60 8
          10 K            27 b            44 s            61 9
          11 L            28 c            45 t            62 +
          12 M            29 d            46 u            63 /
          13 N            30 e            47 v
          14 O            31 f            48 w         (pad) =
          15 P            32 g            49 x
          16 Q            33 h            50 y
让我们再来看一个实际的例子,加深印象!

转换前        10101101        10111010        01110110         
转换后        00101011        00011011        00101001        00110110
十进制        43        27        41        54
对应码表中的值        r        b        p        2

所以上面的24位编码,编码后的Base64值为 rbp2
解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。
(解码只是编码的逆过程,在此我就不多说了,另外有关MIME的RFC还是有很多的,如果需要详细情况请自行查找。)

用更接近于编程的思维来说,编码的过程是这样的:

第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一个目标字符。
然后将第一个字符左移4位加上第二个字符右移4位,即获得第二个目标字符。
再将第二个字符左移2位加上第三个字符右移6位,获得第三个目标字符。
最后取第三个字符的右6位即获得第四个目标字符。

在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了。
 楼主| 发表于 2008-10-27 23:08:45 | 显示全部楼层

判断网页编码

(1)原始方案
System.Text.Encoding.Default
采用当前的默认编码,可以解决大部分问题,但是很多跟情况下同样会出错。

(2)HTTPWebrequest 的CharacterSet(MSND上给的方案,本来应该的做法)
该属性可以返回该网站编码,但是总为空。

(3)老外的解决之道

Sven Groot
I came across a very silly (and annoying) bug in the HttpWebResponse.CharacterSet property. Let's see if you can spot it (code extracted with reflector):

public string get_CharacterSet()
{
&#160;&#160;this.CheckDisposed();
&#160;&#160;string text1 = this.m_HttpResponseHeaders.ContentType;
&#160;&#160;if ((this.m_CharacterSet == null) && !ValidationHelper.IsBlankString(text1))
&#160;&#160;{
&#160; &#160; this.m_CharacterSet = string.Empty;
&#160; &#160; string text2 = text1.ToLower(CultureInfo.InvariantCulture);
&#160; &#160; if (text2.Trim().StartsWith("text/"))
&#160; &#160; {
&#160; &#160;&#160; &#160;this.m_CharacterSet = "ISO-8859-1";
&#160; &#160; }
&#160; &#160; int num1 = text2.IndexOf(";");
&#160; &#160; if (num1 > 0)
&#160; &#160; {
&#160; &#160;&#160; &#160;while ((num1 = text2.IndexOf("charset", num1)) >= 0)
&#160; &#160;&#160; &#160;{
&#160; &#160;&#160; &#160;&#160;&#160;num1 += 7;
&#160; &#160;&#160; &#160;&#160;&#160;if ((text2[num1 - 8] == ';') || (text2[num1 - 8] == ' '))
&#160; &#160;&#160; &#160;&#160;&#160;{
&#160; &#160;&#160; &#160;&#160; &#160; while ((num1 < text2.Length) && (text2[num1] == ' '))
&#160; &#160;&#160; &#160;&#160; &#160; {
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;num1++;
&#160; &#160;&#160; &#160;&#160; &#160; }
&#160; &#160;&#160; &#160;&#160; &#160; if ((num1 < (text2.Length - 1)) && (text2[num1] == '='))
&#160; &#160;&#160; &#160;&#160; &#160; {
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;num1++;
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;int num2 = text2.IndexOf(';', num1);
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;if (num2 > num1)
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;{
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160;&#160;this.m_CharacterSet = text1.Substring(num1, num2).Trim();
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160;&#160;break;
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;}
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;this.m_CharacterSet = text1.Substring(num1).Trim();
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;break;
&#160; &#160;&#160; &#160;&#160; &#160; }
&#160; &#160;&#160; &#160;&#160;&#160;}
&#160; &#160;&#160; &#160;}
&#160; &#160; }
&#160;&#160;}
&#160;&#160;return this.m_CharacterSet;
}
(4)另一种方法(先获取内容,再根据内容来判)

static
string GetHtml(string url, Encoding encoding)&#160;&#160;{&#160; &#160; byte[] buf =
new WebClient().DownloadData(url);&#160; &#160; if (encoding !=
null) return encoding.GetString(buf);&#160; &#160; string html = Encoding.UTF8.GetString(buf);&#160; &#160; encoding = GetEncoding(html);&#160; &#160; if (encoding ==
null
|| encoding == Encoding.UTF8) return html;&#160; &#160; return encoding.GetString(buf);&#160;&#160;}


(5)结合3/4的办法(当然去看HttpWebResponse函数的源代码了)
//得到CharacterSet

private
string getEncoding (HttpWebResponse httpResp)
{
string contentType = httpResp.ContentType ;


int i = contentType.IndexOf("charset=");
if (i>=0)   {   i +=
8;
int j = contentType.IndexOf(';', i);
if (j>=i)   {
return contentType.Substring(i,j-i).Trim();   }
return contentType.Substring(i); }
return
string.Empty;}


[ 本帖最后由 faunus 于 2008-10-27 23:13 编辑 ]
 楼主| 发表于 2008-10-28 08:59:37 | 显示全部楼层

高精度计时

利用QueryPerformanceFrequency和QueryPerformanceCounter
void main() {   
    LARGE_INTEGER lv;

    // 获取每秒多少CPU Performance Tick
    QueryPerformanceFrequency( &lv );

    // 转换为每个Tick多少秒
    double secondsPerTick = 1.0 / lv.QuadPart;
   
    for ( size_t i = 0; i < 100; ++i ) {
        // 获取CPU运行到现在的Tick数
        QueryPerformanceCounter( &lv );

        // 计算CPU运行到现在的时间
        // 比GetTickCount和timeGetTime更加精确
        double timeElapsedTotal = secondsPerTick * lv.QuadPart;
      
        cout.precision( 6 );
        cout << fixed << showpoint << timeElapsedTotal << endl;
        //printf( "%lf \n", timeElapsedTotal ) ;
    }
}
 楼主| 发表于 2008-11-1 19:12:47 | 显示全部楼层

Charset

Charset 和 Encoding 的区别

http://www.cftea.com/c/2008/01/LG3YPDRZSTHTJ2IH.asp



Character Set Recognition&#160; &#160; 字符集识别
http://www.yesky.com/imagesnew/software/css/css2/z_charset.html

简单型的
http://www.jb51.net/article/15764.htm

浏览器
http://hi.baidu.com/19www/blog/item/2d6c9fc6e4a4631d9d163db2.html


浏览器判别顺序:
IE解析网页编码时:HTML内的标签优先,而后才是HTTP header内的讯息;
Mozilla、Mozilla Firefox、Sarafi系列的浏览器:则刚刚相反,HTTP header内的讯息优先,然后是HTML内的标签。UTF-8为3个字节表示一个汉子,而普通的GB2312或BIG5是两个。页面输出时,由于上述原因,使浏览器解析、输出<title></title>的内容时,如果在</title>前有奇数个全角字符时,IE把UTF-8当作两个字节解析时出现半个汉字的情况,这时该半个汉字会和</title>的<结合成一个乱码字,导致IE无法读完<title>部分,使整个页面为空百输出。而这个时候如果察看源文件的话,会发现实际上整个叶面全部已经输出了。
因此最简单的解决办法是再网页文件的<head></head>标签中一定要把字符定义<meta http-equiv="Content-Type" c /> 放在<title></title>之前.


根据http协议和html的规范,有3种办法可以得到一个页面的字符编码: &#160;&#160;
&#160; 1.&#160; &#160; &#160; &#160; An &#160; HTTP &#160; "charset" &#160; parameter &#160; in &#160; a &#160; "Content-Type" &#160; field. &#160; &#160;&#160;
&#160; example: &#160;&#160;
&#160; Content-Type: &#160; text/html; &#160; charset=EUC-JP &#160;&#160;
&#160; &#160;&#160;
&#160; 2.&#160; &#160; &#160; &#160; A &#160; META &#160; declaration &#160; with &#160; "http-equiv" &#160; set &#160; to &#160; "Content-Type" &#160; and &#160; a &#160; value &#160; set &#160; for &#160; "charset". &#160; &#160;&#160;
&#160; example: &#160;&#160;
&#160; <META &#160; http-equiv="Content-Type" &#160; c> &#160;&#160;
&#160; &#160;&#160;
&#160; 3.&#160; &#160; &#160; &#160; The &#160; charset &#160; attribute &#160; set &#160; on &#160; an &#160; element &#160; that &#160; designates &#160; an &#160; external &#160; resource. &#160; &#160;&#160;
&#160; example: &#160;&#160;
&#160; <A &#160; href="http://www.w3.org/" &#160; charset="ISO-8859-1">W3C &#160; Web &#160; site</A> &#160;&#160;
&#160; &#160;&#160;
&#160;&#160; &#160;第一个很少有人会设置,所以,没有默认编码的说法。一般的说,如果第一个没有说明编码的话,必须在后2者中说明编码,这样做的首要条件是:在html的编码中,ascii码仍然可以识别。这样的语言如gb2312,因为英文字符仍然保存为单个字节,和ascii码一样。 &#160;&#160;
&#160; unicode-16的识别: &#160;&#160;
&#160;&#160; &#160;UTF-16使用上述规则无法识别(但是,UTF-8可以),所以,它的识别规则比较特殊。如果一个传输过来的文本,第一个和第二个字节为0xff和0xfe的话(这2个字节的顺序说明了utf-16编码是否是大头在前的),就表明从第三个字节开始,这个文档是使用了UTF-16编码。其识别的处理应该在上述识别方法的前面进行。 &#160;&#160;
&#160; Unicode-8的识别: &#160;&#160;
&#160; utf-8以0xef, &#160; 0xbb, &#160; 0xbf开头,所以,遇到这3个字节的时候,应该可以肯定的说,余下来的字符流是utf-8编码。 &#160;&#160;



[ 本帖最后由 faunus 于 2008-11-1 21:12 编辑 ]
 楼主| 发表于 2008-11-1 20:49:18 | 显示全部楼层

专链转换原理分析

首先要搞懂base64编码,网上有一篇很好的入门教程,地址:http://www.luocong.com/articles/show_article.asp?Article_ID=17
搞懂了base64编码一切都简单了,下面以实例讲解转换过程。例如华军winrar 3.71的下载地址是
http://p2s.newhua.com/down/wrar371sc.exe

1、普通地址转换为迅雷地址
在原地址前面加"AA",后面加"ZZ"(注:不包括引号),地址变为
AAhttp://p2s.newhua.com/down/wrar371sc.exeZZ
此地址base64编码为
QUFodHRwOi8vcDJzLm5ld2h1YS5jb20vZG93bi93cmFyMzcxc2MuZXhlWlo=
迅雷专链即在上地址前加thunder://,即
thunder://QUFodHRwOi8vcDJzLm5ld2h1YS5jb20vZG93bi93cmFyMzcxc2MuZXhlWlo=

2、普通地址转换为快车地址
在原地址前后都加上"[FLASHGET]"(注:不包括引号),地址变为
[FLASHGET]http://p2s.newhua.com/down/wrar371sc.exe[FLASHGET]
此地址base64编码为
W0ZMQVNIR0VUXWh0dHA6Ly9wMnMubmV3aHVhLmNvbS9kb3duL3dyYXIzNzFzYy5leGVbRkxBU0hHRVRd
快车专链即在上地址前加flashget://,注意后面还要加上"&符号",符号怎么得出我也不清楚,我自己在最后后面加的是我个人信息,至今未有人报告转换错误,即
Flashget://W0ZMQVNIR0VUXWh0dHA6Ly9wMnMubmV3aHVhLmNvbS9kb3duL3dyYXIzNzFzYy5leGVbRkxBU0hHRVRd&yinbing1986

3、普通地址转换为旋风地址
旋风相对就简单多了,将原地址直接base64编码为
aHR0cDovL3Aycy5uZXdodWEuY29tL2Rvd24vd3JhcjM3MXNjLmV4ZQ==
旋风专链即在上地址前加qqdl://,即
qqdl://aHR0cDovL3Aycy5uZXdodWEuY29tL2Rvd24vd3JhcjM3MXNjLmV4ZQ==
 楼主| 发表于 2008-11-1 21:17:52 | 显示全部楼层

NChardet 专题

一、什么是NChardet
&#160; &#160; NChardet是mozilla自动字符编码识别程序库chardet的.NET实现,它移植自jchardet,chardet的java版实现,可实现对给定字符流的编码探测。

二、NChardet是如何工作
&#160; &#160; NChardet通过逐个比较输入字符来猜测编码;由于是猜测,所以可能会有不能完全识别的情况;如果输入字符不能确定正确的编码,那么NChardet会给出一组可能的编码值。

三、如何使用NChardet
&#160; &#160; 要使用NChardet来探测编码,需要进行如下步骤。
&#160; &#160; 1、使用制定的语言线索来构造Detector类的实例对象。
&#160; &#160; 2、用实现了ICharsetDetectionObserver接口的对象作为参数来调用Detector类的Init方法。
&#160; &#160; 3、传入要探测的字符流进行编码探测。
&#160; &#160; 4、调用Detector类的DataEnd方法。
&#160; &#160; 5、得到结果或可能的结果集。

四、语言线索
&#160; &#160; 语言线索是一个整数,可用的语言线索有如下几个:
&#160; &#160; 1.&#160; &#160; Japanese
&#160; &#160; 2.&#160; &#160; Chinese
&#160; &#160; 3.&#160; &#160; Simplified Chinese
&#160; &#160; 4.&#160; &#160; Traditional Chinese
&#160; &#160; 5.&#160; &#160; Korean
&#160; &#160; 6.&#160; &#160; Dont know (默认)

五、调用方法
&#160;&#160; &#160;ICharsetDetectionObserver接口只有一个Notify方法,当NChardet引擎认为自己已经探测出正确的编码时,它就会调用这个Notify方法,用户程序可以从这个Nodify方法中得到通知(重写ICharsetDetectionObserver接口的Notify实现)。

六、其它
IE里面的mlang.dll能实现相同的功能。

[ 本帖最后由 faunus 于 2008-11-1 21:42 编辑 ]
 楼主| 发表于 2008-11-1 21:49:25 | 显示全部楼层

SSL

目的:
对于用HttpWebRequest加载证书请求远端https服务器时,发生的
“基础连接已经关闭: 无法与远程服务器建立信任关系。”/
“The underlying connection was closed. Could not establish a secure SSL/TLS connection”错误,我们可以用如下方式解决。
重现:
使用以下代码,你就可以得到这个错误“基础连接已经关闭: 无法与远程服务器建立信任关系”:
using System;
using System.Text;
using System.Net;
using System.IO;
using System.Security.Cryptography.X509Certificates;

using Microsoft.Web.Services2.Security;
using Microsoft.Web.Services2.Security.Tokens;
using Microsoft.Web.Services2.Security.X509;

static void Main(string[] args)
&#160; &#160;&#160; &#160;&#160;&#160;{
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;StringBuilder sb=new StringBuilder();
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;string _strToRequest = "send";

&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;try
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;{
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; //POST请求开始
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; byte[] bt=Encoding.Default.GetBytes("send");
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; HttpWebRequest Req=(HttpWebRequest)System.Net.WebRequest.Create("https://202.108.CCC.XXX:Port//");
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; Req.KeepAlive=true;
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; //Req.Timeout=60000;
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; Req.C;
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; Req.ContentLength=_strToRequest.Length;
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; Req.Method="POST";
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; X509CertificateStore store = X509CertificateStore.CurrentUserStore( X509CertificateStore.MyStore );
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; store.OpenRead();
&#160; &#160;
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; //读取证书的keyid
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; Microsoft.Web.Services2.Security.X509.X509CertificateCollection certs =
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160;&#160;store.FindCertificateByKeyIdentifier( Convert.FromBase64String( "CXv+xZ78zI3qWHGJ6Wh9BF6B23A=" ) );
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; X509SecurityToken token = null;
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; if (certs.Count > 0)
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; {
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160;&#160;// 得到证书存储区的第1个人证书
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160;&#160;token = new X509SecurityToken( ((Microsoft.Web.Services2.Security.X509.X509Certificate) certs[0]) );
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; }
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; if(token != null)
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160;&#160;Req.ClientCertificates.Add(token.Certificate);
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; Req.KeepAlive=true;

&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; Stream ReqStream=Req.GetRequestStream();
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; ReqStream.Write(bt,0,bt.Length);
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; ReqStream.Close();
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; //得到响应
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; HttpWebResponse res=(HttpWebResponse)Req.GetResponse();
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; StreamReader sr=new StreamReader(res.GetResponseStream(),Encoding.Default);
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; sb.Append(sr.ReadToEnd());
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; res.Close();
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; sr.Close();
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;}
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;catch(Exception ex)
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;{&#160; &#160;
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; sb.Remove(0,sb.Length);
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; sb.Append("<?xml version=\"1.0\" encoding=\"gb2312\"?>\n");
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; sb.Append("<slia ver=\"1.0.0\">\n");
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; sb.Append("<result resid=\"501\">"+ex.Message+"</result>\n");
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; sb.Append("</slia>\n");
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;}

&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;Console.WriteLine(sb.ToString());

&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;Console.Read();
&#160; &#160;&#160; &#160;&#160;&#160;}
原因:
证书标识特定的计算机,该计算机的名称位于证书的公共名称中。但是,很容易就会更改计算机的名称或使用客户端配置文件中的“localhost”,这会在客户端和服务器证书中的公共名称之间造成不匹配的情况。在 .NET Framework 1.0 版中,这一不匹配的情况将被忽略,并且将在服务器上引发调用。
从 .NET Framework 1.1 版开始,这一不匹配的情况会引发以下异常:“System.Net.WebException:基础连接已经关闭:无法与远程服务器建立信任关系”。如果您无法配置远程处理客户端以使用证书公共名称,则可以使用客户端应用程序配置文件中的以下设置重写这一不匹配的情况。
<system.net>
&#160; &#160;<settings>
&#160; &#160;&#160; &#160;<servicePointManager
&#160; &#160;&#160; &#160;&#160; &#160;checkCertificateName="true"
&#160; &#160;&#160; &#160;/>
&#160; &#160;</settings>
</system.net>
若要以编程方式使客户端忽略证书名称不匹配,客户端必须创建一个特定类的实例,如果 certificateProblem 值为 0x800c010f,该类将实现 ICertificatePolicy 接口并实现 CheckValidationResult 方法以返回 true。然后,您必须将该对象注册到 System.Net.ServicePointManager 对象,方法是将该对象传递到 ServicePointManager.CertificatePolicy 属性。”
解决之道:
但是用它列出的代码还是不对,我们改为CheckValidationResult无条件返回true即可。如下所示声明一个TrustAllCertificatePolicy类:

public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
&#160; &#160;&#160; &#160;&#160;&#160;{
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;public TrustAllCertificatePolicy()
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;{}

&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;public bool CheckValidationResult(ServicePoint sp,
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; System.Security.Cryptography.X509Certificates.X509Certificate cert,
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; WebRequest req, int problem)
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;{
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; return true;
&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;}
&#160; &#160;&#160; &#160;&#160;&#160;}
然后,在请求之前加上
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
即可。
这样,代码就可以顺利和https服务器建立SSL通道了。

参考MSND(关键)
http://msdn.microsoft.com/en-us/library/y0hedwet.aspx

[ 本帖最后由 faunus 于 2008-11-1 21:51 编辑 ]
您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

QQ|手机版|Archiver|火车采集器官方站 ( 皖ICP备06000549 )

GMT+8, 2024-11-24 19:12

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表