通用采集小工具重構之路——字符處理規則重構


之前由於工作的原因,寫過一個通用網站數據采集的小工具,通過配置XML來采集不同的網站內容。

這段時間工作閑暇之余,覺得有必要重構一下,順便學習學習,特此記錄。

 

字符處理規則重構

字符處理應該算是采集中得一個核心內容,如果在一大串HTML字符串中提取成我們需要的字段。先看看之前的處理方式:

View Code
string temp2;
temp2 = GetStr(str, MyConfig.Url, Lev); //字符截取規則
temp2 = ReplaceStr(temp2, MyConfig.UrlGL, Lev); //字符過濾規則
temp2 = SetCodeing(temp2, MyConfig.UrlBM, Lev);//字符URL編碼規則
temp2 = Myreplace(temp2,MyConfig.UrlGvContent,Lev);//字符替換規則

分析毛病:

1. 客戶端調用次數太多,如果有四個規則則需要調用四個規則。

2. 擴展不靈活,如果以后遇到新的采集需求而現有的規則不滿足要求,需要添加新的規則,則不符合“開閉原則”

 

下面讓我們開始重構吧:

1. 提取公用的規則接口

文字處理規則接口
/// <summary>
    /// 文字處理規則接口
    /// </summary>
    public interface ItextRule
    {
        /// <summary>
        /// 字符處理
        /// </summary>
        /// <param name="sourceStr">待處理字符串</param>
        /// <param name="key">配置關鍵字</param>
        /// <param name="lev">當前層級</param>
        /// <returns></returns>
        string TextPro(string sourceStr,string key,int lev);
    }

2. 建立規則類的抽象類,寫入一些公用的方法

字符處理規則基礎類
 /// <summary>
    /// 字符處理規則基礎類
    /// </summary>
    public abstract class TextRuleBase
    {
        private string myKey = string.Empty;

        public TextRuleBase(string _key)
        {
            myKey = _key;
        }

        /// <summary>
        /// 獲取配置文件的值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="lev"></param>
        /// <returns></returns>
        protected string[] GetValue(string key,int lev)
        {
            string str = string.Empty;
            string temp = string.Empty;
            string tempKey = key + myKey + lev;
            bool Istrue = true; 
            while(Istrue) //循環讀配置,知道為空
            {
                temp = SiteConfig.ConfigByKey(tempKey);
                if (temp == "")
                {
                    Istrue = false;
                }
                else
                {
                    str += temp + "|";
                    tempKey += lev;
                }
            }

            return str.Split(new char[]{'|'},StringSplitOptions.RemoveEmptyEntries);
            
        }

        /// <summary>
        /// 具體規則處理 強制子類實現
        /// </summary>
        /// <param name="sourceStr"></param>
        /// <param name="Content"></param>
        /// <returns></returns>
        protected abstract string TextPro(string sourceStr, string[] Contents);
       
    }

3. 建立字符規則類,按照上面的邏輯分別建立4個字符規則類,繼承接口和抽象類

字符截取規則 基本規則
 /// <summary>
    /// 字符截取規則 基本規則
    /// </summary>
    public class TextIntercept :TextRuleBase, ItextRule
    {
        public TextIntercept():base("")
        {
        }


        #region ItextRule 公開成員
        /// <summary>
        /// 字符截取規則具體實現(多次)
        /// </summary>
        /// <param name="sourceStr"></param>
        /// <param name="key"></param>
        /// <param name="lev"></param>
        /// <returns></returns>
        public string TextPro(string sourceStr, string key, int lev)
        {
            return TextPro(sourceStr,GetValue(key,lev));
        }

        #endregion
       


        #region 內部強制私有方法

        /// <summary>
        /// 字符截取規則具體實現(多次)
        /// </summary>
        /// <param name="sourceStr"></param>
        /// <param name="Content"></param>
        /// <returns></returns>
        protected override string TextPro(string sourceStr, string[] Contents)
        {
            string relText = sourceStr;
            foreach (string value in Contents)
            {
                if (value != "")
                {
                    relText = Function.GetStr(relText, value, MyConfig.Key);
                }
            }

            Console.WriteLine("字符截取規則結果:" + relText);
            Console.WriteLine("");
            return relText;
        }
        #endregion

       
    }

這里就只建立一個示例,其他同。或詳見CODE

4. 建立一個高層接口,供客戶端直接調用,內部封裝好各種規則(根據配置)

字符處理規則的高層接口
  /// <summary>
    /// 字符處理規則的高層接口
    /// </summary>
    public class TextRuleAll:ItextRule
    {
        private Dictionary<string, IList<ItextRule>> ruleList = new Dictionary<string, IList<ItextRule>>();


        #region ItextRule 成員

        public string TextPro(string sourceStr, string key, int lev)
        {
            string dicKey = key + lev;
            string returnStr = string.Empty;
            if (!ruleList.ContainsKey(dicKey))
            {
                IList<ItextRule> list = new List<ItextRule>();

                #region 根據配置構建關鍵字規則列表
                
                foreach (string vale in MyConfig.AllTextRules())
                {
                    string[] temp = vale.Split('.');
                    string xmlKey = temp[temp.Length - 1];
                    if (xmlKey == "TextIntercept") //寫死 字符截取規則為基本規則
                        xmlKey = "";
                    if (SiteConfig.ConfigByKey(key + xmlKey + lev) != "") //XML文件有此配置關鍵字
                    {
                        list.Add((ItextRule)Assembly.Load("Demo1").CreateInstance(vale));
                 
                    }
                }
                
                #endregion

                ruleList.Add(dicKey,list);
            }

            IList<ItextRule> mylist = ruleList[dicKey];
            if (mylist != null && mylist.Count > 0) //循環執行各種規則處理
            {
                returnStr = sourceStr;
                foreach (ItextRule irule in mylist)
                    returnStr = irule.TextPro(returnStr, key, lev);
            }
            return returnStr;
        }

        #end

5. 配置文件

XML配置
<MyConfig>
    <!--字符處理擴展規則列表-->
    <!--TextIntercept為截取規則-->
    <!--StaticReplace為靜態替換規則-->
    <AllTextRules>Collect.TextRule.TextIntercept,Collect.TextRule.StaticReplace,Collect.TextRule.TextUrlEncode,Collect.TextRule.TextFilter</AllTextRules>


    
    <!--TextIntercept截取規則配置-->
    <Name1>郵件地址是[內容]</Name1>
    
    <!--StaticReplacej靜態替換配置-->
    <NameStaticReplace1>#,@</NameStaticReplace1>
    <NameStaticReplace11>fuwentao,fwt</NameStaticReplace11>
    
    <!--中文URL編碼規則配置-->
    <NameTextUrlEncode1>city=[內容]</NameTextUrlEncode1>
    
    <!--過濾規則配置-->
    <NameTextFilter1>.com,[內容]http</NameTextFilter1>
</MyConfig>

重構完了,讓我們再看看客戶端的調用:

string testStr = "我是fuwentao,我的郵件地址是fwt1314111#163.com,網址http://www.mywaysoft.net/city=上海";
TextRuleAll cmd = new TextRuleAll();
string rel= cmd.TextPro(testStr, "Name", 1); //結果

就一句cmd.TextPro搞定!是不是比之前簡單多了。

並且,這樣靈活性也很強,以后如果要增加新的處理規則,則只需要建立一個規則類,然后再配置文件中配置一下就OK啦。

 

DEMO下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM