8、多层次网页数据抓取

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using System.Data.OleDb;

namespace Institute
{
    public partial class Form1 : Form
    {
        public Form1()
        {

            InitializeComponent();

        }

        private DataTable dtCondition = new DataTable("Condition");
        public DataTable DtCondition
        {
            set { dtCondition = value; }
            get { return dtCondition; }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {

            ReadCondition();
            CatchPage("http://itp.ne.jp");
            MessageBox.Show("URL获取完毕!");
        }

        private void btnGetData_Click(object sender, EventArgs e)
        {
            CatchArea();
        }

        #region CatchPage
        //获取URL
        public void CatchPage(string requestUrl)
        {
            //获取页面并解析出所需的URL
            string[] groupArray = GenreSearch(webRequest(requestUrl));

            //dtCondition.Columns.Add("URL");
            for ( int i = 0; i < DtCondition.Rows.Count; i++ )
            {
                int key = 1;
                for ( int j = 0; j < groupArray.Length - 1; j++ )
                {
                    string strCondition = Regex.Match(groupArray[j], ">.*?</h2>|>.*").Value.Replace(">", "").Replace("</h2", "").Trim();
                    if ( ( DtCondition.Rows[i][0].ToString() ) == strCondition )
                    {
                        MatchCollection request = Regex.Matches(groupArray[j], "\".*?\"");
                        if ( DtCondition.Rows[i][key].ToString() != "" )
                        {
                            CatchChildPage("http://itp.ne.jp" + request[0].Value, key++, i);
                        }
                        else
                        {
                            CatchChildPage("http://itp.ne.jp" + request[0].Value, "LastGenList.txt");
                        }
                        break;
                    }
                }
            }
        }
        #endregion

        #region CatchChildPage_1
        //有下级条件
        public void CatchChildPage(string requestUrl, int key, int i)
        {
            requestUrl = requestUrl.Replace("\"", "");
            string[] groupArray = GetHref(webRequest(requestUrl));
            //DataTable dtLastUrl = null;
            for ( int j = 1; j < groupArray.Length; j++ )
            {
                string strCondition = Regex.Match(groupArray[j], @">.*?<").Value;
                strCondition = strCondition.Substring(1, strCondition.IndexOf('(') - 1).Trim();
                if ( strCondition.Equals(DtCondition.Rows[i][key].ToString()) && key < 4 )
                {
                    MatchCollection request = Regex.Matches(groupArray[j], "\".*?\"");
                    if ( DtCondition.Rows[i][++key].ToString() != "" )
                    {
                        //调用CatchChildPage_1
                        CatchChildPage("http://itp.ne.jp" + request[1].Value, key, i);
                    }
                    else
                    {
                        //调用CatchChildPage_2
                        CatchChildPage("http://itp.ne.jp" + request[0].Value);
                    }
                    break;
                }
            }
        }
        #endregion

        #region CatchChildPage_2
        //没有下级条件
        public void CatchChildPage(string requestUrl)
        {

            requestUrl = requestUrl.Replace("\"", "");
            string[] groupArray = GetHref(webRequest(requestUrl));
            //DataTable dtLastUrl = new DataTable("LastUrl");
            //dtLastUrl.Columns.Add();
            for ( int j = 1; j < groupArray.Length; j++ )
            {
                MatchCollection request = Regex.Matches(groupArray[j], "\".*?\"");
                string strCount = Regex.Match(groupArray[j], @"\(.*?\)").Value;
                //匹配到1一个以上的URL说明还有下一级,继续向下匹配
                if ( request.Count > 1 )
                {
                    CatchChildPage("http://itp.ne.jp" + request[1].Value);
                }
                //匹配到1个URL且没有下一级
                else if ( request.Count == 1 && strCount != "(0件)" )
                {
                    //调用CatchChildPage_3
                    CatchChildPage("http://itp.ne.jp" + request[0].Value, "LastGenList.txt");

                }
            }
        }
        #endregion


        #region CatchChildPage_3
        //取都省府县各级的URL
        public void CatchChildPage(string requestUrl, string txt)
        {
            requestUrl = requestUrl.Replace("\"", "");
            string[] groupArray = GetHref(webRequest(requestUrl));
            for ( int j = 1; j < groupArray.Length; j++ )
            {
                MatchCollection request = Regex.Matches(groupArray[j], "\".*?\"");
                string strCount = Regex.Match(groupArray[j], @"\(.*?\)").Value;
                //匹配到1一个以上的URL说明还有下一级,继续向下匹配
                if ( request.Count > 1 )
                {
                    CatchChildPage("http://itp.ne.jp" + request[1].Value, txt);
                }
                //匹配到1个URL且没有下一级
                else if ( request.Count == 1 && strCount != "(0件)" )
                {
                    using ( StreamWriter writer = new StreamWriter(Application.StartupPath + @"\" + txt, true) )
                    {
                        writer.WriteLine("http://itp.ne.jp" + request[0].Value.Replace("\"", "").Replace("amp;", ""));
                    }
                }
            }
        }
        #endregion

        #region webRequest
        //获取requestUrl所指向的页面
        public string webRequest(string requestUrl)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            string results = null;
            try
            {
                request = (HttpWebRequest)WebRequest.Create(requestUrl);
                //代理设置
                request.Proxy = new WebProxy("http://66.35.68.145:3128");
                request.Method = "GET";
                request.Timeout = 1000 * 60 * 2;
                request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
                request.KeepAlive = true;
                request.ReadWriteTimeout = 1000 * 60 * 2;
                response = (HttpWebResponse)request.GetResponse();
                using ( StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("Shift_JIS")) )
                {
                    results = reader.ReadToEnd();
                }
            }
            catch
            {
                //如果捕获异常,则延迟1秒
                Thread.Sleep(1000);
            }
            finally
            {
                try
                {
                    response.Close();
                }
                catch
                {
                    //捕获到response异常,则重新执行GetGenre函数(一般response异常为response=null,既连接异常)
                    results = webRequest(requestUrl);
                }
            }
            //如果results的值为空则重新执行GetGenre函数(此种情况一般发生在连接断开时间比较长的情况下)
            if ( results == null )
            {
                results = webRequest(requestUrl);
            }

            return results;
        }
        #endregion

        #region GetHref
        //从获取的页面中解析出所需的数据
        public string[] GetHref(string results)
        {
            results = results.Substring(results.IndexOf("<li>"));
            results = results.Remove(results.IndexOf("</ul>"));
            results = Regex.Replace(results, "<(?!a|/a|li).*?>|\r|\n|\t", "");
            results = Regex.Replace(results, @"<input[^>]*/?>", "");
            string[] group = Regex.Split(results, "<li>");
            return group;
        }
        #endregion

        //解析主页中的数据
        public string[] GenreSearch(string results)
        {
            results = results.Substring(results.IndexOf("<h1>ジャンルから探す</h1>"));
            results = results.Remove(results.IndexOf("</div>")).Replace(" ", "").Replace("<br>", "").Replace("\n", "");
            results = Regex.Replace(results, @"<span>.*?</span>", "", RegexOptions.IgnoreCase);
            results = Regex.Replace(results, @"<(?!a|/a|/h2).*?>|\r|\n|\t", "");
            string[] group = Regex.Split(results, "</a>");
            return group;
        }

        //读取表[条件ジャンル]
        private void ReadCondition()
        {
            using ( OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Application.StartupPath + @"\A23:施設情報20130712.mdb") )
            {
                string sqlStr = "SELECT [施設1],[施設2],[施設3],[施設4] FROM [条件ジャンル] ";
                OleDbDataAdapter adapter = new OleDbDataAdapter(sqlStr, con);
                con.Open();
                adapter.Fill(DtCondition);
            }
        }

        //读取TXT中的数据存入DATATABLE中
        public DataTable ReadUrlTxt()
        {
            DataTable dtLastUrl = new DataTable("Url");
            dtLastUrl.Columns.Add();

            using ( StreamReader reader = new StreamReader(Application.StartupPath + @"\LastGenList.txt") )
            {
                while ( !reader.EndOfStream )
                {
                    DataRow drNew = dtLastUrl.NewRow();
                    drNew[0] = reader.ReadLine();
                    dtLastUrl.Rows.Add(drNew);
                }
            }
            return dtLastUrl;
        }

        public void CatchArea()
        {
            DataTable lastUrl = ReadUrlTxt();
            foreach ( DataRow row in lastUrl.Rows )
            {
                int count = GetWebData(row[0].ToString());

                count = (int)Math.Ceiling(count / 50.0000000);
                for ( int i = 2; i <= count; i++ )
                {
                    string requestUrl = row[0].ToString().Replace("&pg=1", "&pg=" + i.ToString());

                    GetWebData(requestUrl);
                }
            }
        }

        public int GetWebData(string requestUrl)
        {
            string results = webRequest(requestUrl + "&num=50");
            results = results.Substring(results.IndexOf("</button>"));
            results = Regex.Replace(results, @"\n|\r|\t", "").Replace(" ", "");
            //count为检索结果的数目
            string strCount = Regex.Match(results, @"<li.*?>.*?</li>").Value;
            strCount = Regex.Match(strCount, @"[0-9]+").Value;
            int count = Convert.ToInt32(strCount);

            //地址
            string area = Regex.Match(results, @">.*?<h4").Value;
            area = Regex.Replace(area, @"^>|<[^>]*>|>|<h4", "");
            string[] arrayArea = area.Split(';');
            //分类
            string type = Regex.Match(results, @"全ジャンル.*?</div>").Value;
            type = Regex.Replace(type, @"^.*?>|<[^>]*>|>", "");
            string[] arrayType = arrayType = type.Split(';');
            MatchCollection article = Regex.Matches(results, @"<article>.*?</article>");
            using ( OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Application.StartupPath + @"\A23:施設情報20130712.mdb") )
            {
                OleDbCommand cmd = con.CreateCommand();
                con.Open();
                foreach ( Match match in article )
                {
                    //设施名称
                    string name = Regex.Match(match.Value, "<h4class=\"clearfix\">.*?</a>").Value;
                    name = Regex.Replace(name, @"<[^>]*>", "");
                    //地址和邮编
                    string zipCode = Regex.Match(match.Value, @"〒.*?<").Value;
                    string address = zipCode.Substring(10).Replace("<", "");
                    zipCode = zipCode.Substring(0, 10).Trim();

                    //地图地址
                    string mapUrl = Regex.Match(match.Value, address + @"<.*?>地図・ナビ").Value;
                    mapUrl = "http://itp.ne.jp" + Regex.Match(mapUrl, "\".*?\"").Value.Replace("\"", "");
                    string mapResult = webRequest(mapUrl);
                    //mapResult = mapResult.Substring(mapResult.IndexOf("<!--** 地図表示 START **-->"));
                    //mapResult = mapResult.Remove(mapResult.IndexOf(" <!--** 地図表示 END **-->"));
                    //经度
                    string longitude = Regex.Match(mapResult, "<input.*?/>").Value;
                    //纬度
                    string latitude = Regex.Match(mapResult, "<input.*?/>").NextMatch().Value;

                    longitude = Regex.Match(longitude, "value=\".*?\"").Value.Replace("value=", "").Replace("\"", "");
                    latitude = Regex.Match(latitude, "value=\".*?\"").Value.Replace("value=", "").Replace("\"", "");
                    if ( longitude == "" )
                    {  
                        mapResult = mapResult.Substring(mapResult.IndexOf("<input"));
                        mapResult = mapResult.Remove(mapResult.IndexOf("</script>"));
                        mapResult = Regex.Match(mapResult, "<script.*?>").Value;
                        mapUrl = Regex.Match(mapResult, "\".*?\"").NextMatch().Value.Replace("\"", "");
                        mapResult = webRequest(mapUrl);
                        longitude = Regex.Match(mapResult, @"val\(.*?\)").Value.Replace("val(\"", "").Replace("\")", "");
                        latitude = Regex.Match(mapResult, @"val\(.*?\)").NextMatch().Value.Replace("val(\"", "").Replace("\")", "");
                    }

                    //电话
                    string tel = Regex.Match(match.Value, @"TEL.*?</p>").Value.Replace("TEL</span>", "").Replace("</p>", "");
                    tel = Regex.Replace(tel, "<[^>]*>", "");
                    
                    string telNo = Regex.Match(tel, "[0-9].*").Value;
                    tel = Regex.Replace(tel, "[0-9].*", "");

                    //链接
                    string url = Regex.Match(match.Value, @"URL.*?</br>").Value.Replace("URL</span>", "").Replace("</br>", "");
                    //主页
                    string homePage = Regex.Match(match.Value, @"<.*?>HP").Value;
                    if ( homePage != "" )
                    {
                        homePage = "http://itp.ne.jp" + Regex.Match(homePage, "\".*?\"").Value.Replace("\"", "").Replace("amp;", "");
                    }
                    if ( arrayType.Length >= 4 )
                    {
                        cmd.CommandText = "INSERT INTO [施設情報] (住所1,住所2,住所3,ジャンル1,ジャンル2,ジャンル3,ジャンル4,施設名称,郵便No,住所,TEL1記号,TEL1No,経度,緯度,公式URL,URL)"
                        + " VALUES ('" + arrayArea[0] + "','" + arrayArea[1] + "','" + arrayArea[2] + "','" + arrayType[0] + "','" + arrayType[1] + "','" + arrayType[2]
                        + "','" + arrayType[3] + "','" + name + "','" + zipCode + "','" + address + "','" + tel + "','" + telNo + "'," + Convert.ToInt32(longitude) + "," + Convert.ToInt32(latitude)
                        + ",'" + homePage + "','" + url + "')";
                    }
                    else if ( arrayType.Length == 3 )
                    {
                        cmd.CommandText = "INSERT INTO [施設情報] (住所1,住所2,住所3,ジャンル1,ジャンル2,ジャンル3,ジャンル4,施設名称,郵便No,住所,TEL1記号,TEL1No,経度,緯度,公式URL,URL)"
                       + " VALUES ('" + arrayArea[0] + "','" + arrayArea[1] + "','" + arrayArea[2] + "','" + arrayType[0] + "','" + arrayType[1] + "','" + arrayType[2]
                       + "','" + "','" + name + "','" + zipCode + "','" + address + "','" + tel + "','" + telNo + "'," + Convert.ToInt32(longitude) + "," + Convert.ToInt32(latitude)
                       + ",'" + homePage + "','" + url + "')";
                    }
                    else if ( arrayType.Length == 2 )
                    {
                        cmd.CommandText = "INSERT INTO [施設情報] (住所1,住所2,住所3,ジャンル1,ジャンル2,ジャンル3,ジャンル4,施設名称,郵便No,住所,TEL1記号,TEL1No,経度,緯度,公式URL,URL)"
                       + " VALUES ('" + arrayArea[0] + "','" + arrayArea[1] + "','" + arrayArea[2] + "','" + arrayType[0] + "','" + arrayType[1] + "','"
                       + "','" + "','" + name + "','" + zipCode + "','" + address + "','" + tel + "','" + telNo + "'," + Convert.ToInt32(longitude) + "," + Convert.ToInt32(latitude)
                       + ",'" + homePage + "','" + url + "')";
                    }
                    else if ( arrayType.Length == 1 )
                    {
                        cmd.CommandText = "INSERT INTO [施設情報] (住所1,住所2,住所3,ジャンル1,ジャンル2,ジャンル3,ジャンル4,施設名称,郵便No,住所,TEL1記号,TEL1No,経度,緯度,公式URL,URL)"
                       + " VALUES ('" + arrayArea[0] + "','" + arrayArea[1] + "','" + arrayArea[2] + "','" + arrayType[0] + "','" + "','"
                       + "','" + "','" + name + "','" + zipCode + "','" + address + "','" + tel + "','" + telNo + "'," + Convert.ToInt32(longitude) + "," + Convert.ToInt32(latitude)
                       + ",'" + homePage + "','" + url + "')";
                    }

                    cmd.ExecuteNonQuery();
                }
            }
            return count;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Delphi是一种用于开发应用程序的编程语言,它也可以用来进行网页数据抓取。在Delphi中,可以使用网络组件或第三方库来实现网页数据抓取的功能。一般来说,网页数据抓取的流程包括发送HTTP请求、接收和解析服务器响应、提取所需的数据等步骤。 首先,需要使用Delphi的网络组件或第三方库发送HTTP请求,请求特定网页的内容。随后,需要处理服务器返回的响应数据,在其中找到所需的信息,并对其进行解析。常用的解析方式包括正则表达式、HTML解析器等。最后,将解析得到的数据存储下来,或者进行后续的处理和分析。 在实际操作中,可以使用Delphi的网络组件TIdHTTP来发送HTTP请求,获取网页内容。同时,可以使用TStringList等组件来处理服务器响应的文本数据,并通过正则表达式或HTML解析器获取所需的数据。另外,也可以使用第三方库如REST客户端组件来简化HTTP请求的发送和响应的处理。 需要注意的是,进行网页数据抓取时,应当遵守相关的网络伦理规范和法律法规,不得进行非法、侵权或侵犯隐私的行为。另外,网页数据抓取也可能会受到目标网站的反爬虫机制的限制,需要进行相应的技术应对。 综上所述,Delphi可以通过网络组件或第三方库实现网页数据抓取的功能,可以发送HTTP请求、接收和解析服务器响应,提取所需的数据。在进行网页数据抓取时,需要遵守相关的法律法规和伦理规范,同时也要注意目标网站的反爬虫机制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值