技术图文:如何利用C#寻找免费的IP代理服务器?

背景

我们在前面已经介绍过很多网络爬虫的图文:

这里有一个潜在的问题,如果网络请求过于频繁,会被对方服务器封掉IP,导致无法获取数据。

解决方案有两个:一个是降低请求的频率,另一个是使用 IP 代理服务器,即通过不同的 IP 代理服务器来进行网络请求,这样对方服务器就会认为是不同 IP 进行的网络请求,不会判定为异常,被封掉。

今天,咱们就一起通过程序来寻找免费的代理服务器,并通过代理服务器来下载 CSDN 博主的图文。


技术分析

获取免费 IP 代理服务器的网页如下:

IP代理服务器网页

该网页采用分页的方式进行显示,每页显示100条数据,对应的网址如下:

<u>第一页</u>

https://www.xicidaili.com/wt/1

<u>第二页</u>

https://www.xicidaili.com/wt/2

以此类推,我们就得到抓取网页的 URL 地址。

我们再来看一下网页的源码。

网页源码

所有数据全部放置在 <tr> 标签中,只要我们获取对应网页的 HTML DOM TREE 即可。


代码实现

Step1 创建存储 IP 代理服务器的结构 ProxyDataItem

public class ProxyDataItem
{
    /// <summary>
    /// 国家
    /// </summary>
    public string Country { get; set; } = "cn";
    /// <summary>
    /// ip 地址
    /// </summary>
    public string IpAddress { get; set; } = string.Empty;
    /// <summary>
    /// 端口号
    /// </summary>
    public string Port { get; set; } = string.Empty;
    /// <summary>
    /// 服务器地址
    /// </summary>
    public string ServerAddress { get; set; } = string.Empty;
    /// <summary>
    /// 是否匿名
    /// </summary>
    public string IsAnonymous { get; set; } = string.Empty;
    /// <summary>
    /// 速度
    /// </summary>
    public string Speed { get; set; } = string.Empty;
    /// <summary>
    /// 连接时间
    /// </summary>
    public string ConnectionTime { get; set; } = string.Empty;
}

Step2 获取给定 URL 地址的 HTML DOM TREE。

public static IHtmlDocument GetHtmlDocument(string url)
{
    IHtmlDocument document;
    try
    {
        document = new JumonyParser().LoadDocument(url);
    }
    catch
    {
        document = null;
    }
    return document;
}

Step3 获取 IP 代理服务器的列表。

public static string EntryPoint = @"https://www.xicidaili.com/";

public static List<ProxyDataItem> GetProxy(int page)
{
    List<ProxyDataItem> result = new List<ProxyDataItem>();

    string url = EntryPoint + @"/wt/" + page;
    IHtmlDocument document = HtmlSpiter.GetHtmlDocument(url);
    if (document == null)
        return result;

    List<IHtmlElement> lists = document.Find("tr").ToList();
    for (int i = 1; i < lists.Count; i++)
    {
        ProxyDataItem item = new ProxyDataItem();
        List<IHtmlElement> lst = lists[i].Find("td").ToList();
        try
        {
            item.Country = lst[0].FindFirst("img").Attribute("alt").AttributeValue;
            item.IpAddress = lst[1].InnerHtml();
            item.Port = lst[2].InnerHtml();
            item.ServerAddress = lst[3].FindFirst("a").InnerHtml();
            item.IsAnonymous = lst[4].InnerHtml();
            item.Speed = lst[6].FindFirst("div").Attribute("title").AttributeValue;
            item.ConnectionTime = lst[7].FindFirst("div").Attribute("title").AttributeValue;
            result.Add(item);
        }
        catch
        {
            ;
        }
    }
    return result;
}

Step4 验证 IP 代理服务器的有效性。

通过该 IP 代理服务器向百度服务器发出访问请求,如果返回的响应中包含“百度”这个字符串,说明通过该 IP 代理服务器能够访问百度主页,也即该 IP 代理服务器有效。

public static bool ValidateProxy(ProxyDataItem proxy)
{
    if (proxy == null)
        throw new ArgumentNullException();

    string address = proxy.IpAddress;
    int port;
    if (int.TryParse(proxy.Port, out port) == false)
        return false;
    
    try
    {
        WebProxy proxyObject = new WebProxy(address, port);
        HttpWebRequest req = WebRequest.Create("https://www.baidu.com") as HttpWebRequest;
        if (req == null)
            return false;

        req.Proxy = proxyObject; //设置代理
        HttpWebResponse resp = (HttpWebResponse) req.GetResponse();
        Encoding bin = Encoding.GetEncoding("UTF-8");
        using (StreamReader sr = new StreamReader(resp.GetResponseStream(), bin))
        {
            string str = sr.ReadToEnd();
            if (str.Contains("百度"))
            {
                resp.Close();
                return true;
            }
            return false;
        }
    }
    catch
    {
        return false;
    }
}

Step5 通过代理服务器爬取 CSDN 博主网页。

public static bool SaveToHtml(string url, string fileName, ProxyDataItem proxy)
{
    string address = proxy.IpAddress;
    int port;
    if (int.TryParse(proxy.Port, out port) == false)
        return false;

    try
    {
        WebProxy proxyObject = new WebProxy(address, port);
        HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
        if (request == null)
            return false;

        request.Proxy = proxyObject; //设置代理
        HttpWebResponse resp = (HttpWebResponse) request.GetResponse();
        Encoding bin = Encoding.GetEncoding("UTF-8");
        using (StreamReader sr = new StreamReader(resp.GetResponseStream(), bin))
        {
            string str = sr.ReadToEnd();
            StreamWriter vStreamReader = new StreamWriter(fileName, false, Encoding.UTF8);
            vStreamReader.Write(str);
            vStreamReader.Flush();
            vStreamReader.Close();
        }
        return true;
    }
    catch
    {
        return false;
    }
}

总结

我们来看一下从网站爬取的 IP 代理服务器列表(98条记录):

IP代理服务器列表

经过验证的 IP 代理服务器列表(18条记录):

有效IP代理

爬取 CSDN 博主的网页:

博主网页

有关爬取 CSDN 博主网页的图文可以参见:如何利用C#爬取CSDN的博客文章?

CSDN文章列表

爬取的网页列表:

文档列表

好了,今天就到这里吧!希望本次介绍的技术对大家有用。See You!


相关图文

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容

  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,946评论 6 13
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,094评论 1 32
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,466评论 1 45
  • 骤雨寒蝉鸣淒切, 长亭挽清风。 愁绪又无言, 都门帐饮, 泪眼两相看。 多情自古伤离别, 留恋何处去。 晓风残月歇...
    镜汐流年_宁君安阅读 189评论 3 4
  • (稻盛哲学学习会)打卡第57天 姓名:周琪 部门:业务部 组别:待定 【知~学习】 诵读《活法》第五章:与宇宙潮流...
    Lillian_Wellin阅读 219评论 0 0