using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.Net;
using System.IO;
using System.Text;
using System.Collections;
using System.Text.RegularExpressions;

namespace UUN
{
    /// <summary>
    /// 图片采集对象
    /// </summary>
    public class 图片采集
    {
        private HttpContext HC;
        private SqlConnection 连接;
        private int 编码;
        private int ID;
        /// <summary>
        /// 创建一个图片采集对象
        /// </summary>
        /// <param name="HC">HTTP信息</param>
        /// <param name="连接">数据库连接</param>
        /// <param name="ID">图片采集网站ID</param>
        public 图片采集(HttpContext HC, SqlConnection 连接, int ID)
        {
            this.HC = HC;
            this.连接 = 连接;
            this.ID = ID;

            this.编码 = 获取编码();
        }

        private int 获取编码()
        {
            int 返回值;
            SqlCommand 语句 = new SqlCommand("SELECT [字符编码] FROM [" + 程序.数据表前缀 + "内容_图片采集_网站] WHERE [ID]=" + ID, 连接);
            SqlDataReader 读取 = 语句.ExecuteReader();
            if (读取.Read())
                返回值 = Convert.ToInt32(读取["字符编码"]);
            else
            {
                读取.Close();
                throw new Exception("图片采集网站不存在");
            }
            读取.Close();

            return 返回值;
        }
        /// <summary>
        /// 将相对地址转换为绝对地址
        /// </summary>
        /// <param name="当前地址">当前网页的地址</param>
        /// <param name="文件地址">目标网页的地址</param>
        /// <returns></returns>
        public String 处理地址(String 当前地址, String 文件地址)
        {
            if (文件地址.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
                return 文件地址;
            else if (文件地址.StartsWith("/"))
                return 获取主机名(当前地址) + 文件地址;
            else
                return 获取文件夹(当前地址) + 文件地址;
        }
        private String 获取主机名(String 地址)
        {
            地址 = 地址.Replace("\\", "/");
            int 斜杠位置 = 地址.IndexOf("/", 8);
            if (斜杠位置 == -1)
                return 地址;
            else
                return 地址.Substring(0, 斜杠位置);
        }
        private String 获取文件夹(String 地址)
        {
            地址 = 地址.Replace("\\", "/");
            int 斜杠位置 = 地址.LastIndexOf("/");
            if (斜杠位置 < 8)
                return 地址 + "/";
            else
                return 地址.Substring(0, 斜杠位置 + 1);
        }
        /// <summary>
        /// 获取网页的内容
        /// </summary>
        /// <param name="网页地址">网页的地址</param>
        /// <returns></returns>
        public String 获取网页内容(String 网页地址)
        {
            WebClient WC = new WebClient();
            WC.Encoding = Encoding.GetEncoding(编码);

            String 返回值 = "";
            try
            {
                返回值 = WC.DownloadString(网页地址);
            }
            catch { }

            return 返回值;
        }
        /// <summary>
        /// 获取标题和地址信息
        /// </summary>
        /// <param name="列表地址">文章列表的地址</param>
        /// <param name="网页内容">列表网页的内容</param>
        /// <param name="使用通配符">表达式是否使用通配符</param>
        /// <param name="_表达式">获取标题和地址的表达式</param>
        /// <param name="标题和地址">标题和地址的返回值</param>
        public void 获取标题和地址(String 列表地址, String 网页内容, bool 使用通配符, String _表达式, out Hashtable 标题和地址)
        {
            String 内容 = 网页内容;

            标题和地址 = new Hashtable();
            Regex 表达式 = new Regex(使用通配符 ? 常用.通配符转义(_表达式) : _表达式);
            MatchCollection 所有结果 = 表达式.Matches(内容);
            for (int i = 0; i < 所有结果.Count; i++)
            {
                Match 结果 = 所有结果[i];
                String 地址 = 处理地址(列表地址, HttpUtility.HtmlDecode(结果.Groups["地址"].Value));
                String 标题 = HttpUtility.HtmlDecode(结果.Groups["标题"].Value);
                if (地址 != "")
                    标题和地址.Add(i, new String[] { 地址, 标题 });
            }
        }
        /// <summary>
        /// 获取列表的下页地址
        /// </summary>
        /// <param name="网页地址">列表网页的地址</param>
        /// <param name="网页内容">列表网页的内容</param>
        /// <param name="使用通配符">表达式是否使用通配符</param>
        /// <param name="_表达式">获取下页地址的表达式</param>
        /// <param name="页码">获取下页的页码</param>
        /// <returns></returns>
        public String 获取下页地址(String 网页地址, String 网页内容, bool 使用通配符, String _表达式, int 页码)
        {
            if (_表达式 == "")
                return "";
            _表达式 = _表达式.Replace("#页码#", 页码.ToString());
            Regex 表达式 = new Regex(使用通配符 ? 常用.通配符转义(_表达式) : _表达式);
            MatchCollection 所有结果 = 表达式.Matches(网页内容);
            if (所有结果.Count < 1)
                return "";

            return 处理地址(网页地址, HttpUtility.HtmlDecode(所有结果[0].Groups["下页地址"].Value));
        }
        /// <summary>
        /// 获取列表的上页地址
        /// </summary>
        /// <param name="网页地址">列表网页的地址</param>
        /// <param name="网页内容">列表网页内容</param>
        /// <param name="使用通配符">表达式是否使用通配符</param>
        /// <param name="_表达式">获取上页地址的表达式</param>
        /// <param name="页码">列表上页的页码</param>
        /// <returns></returns>
        public String 获取上页地址(String 网页地址, String 网页内容, bool 使用通配符, String _表达式, int 页码)
        {
            if (_表达式 == "")
                return "";
            _表达式 = _表达式.Replace("#页码#", 页码.ToString());
            Regex 表达式 = new Regex(使用通配符 ? 常用.通配符转义(_表达式) : _表达式);
            MatchCollection 所有结果 = 表达式.Matches(网页内容);
            if (所有结果.Count < 1)
                return "";

            return 处理地址(网页地址, HttpUtility.HtmlDecode(所有结果[0].Groups["上页地址"].Value));
        }
        /// <summary>
        /// 获取列表的总页数
        /// </summary>
        /// <param name="网页内容">列表网页的内容</param>
        /// <param name="使用通配符">表达式是否使用通配符</param>
        /// <param name="_表达式">获取列表总页数的表达式</param>
        /// <returns></returns>
        public String 获取总页数(String 网页内容, bool 使用通配符, String _表达式)
        {
            if (_表达式 == "")
                return "-";

            Regex 表达式 = new Regex(使用通配符 ? 常用.通配符转义(_表达式) : _表达式);
            MatchCollection 所有结果 = 表达式.Matches(网页内容);
            if (所有结果.Count < 1)
                return "-";

            return 所有结果[0].Groups["总页数"].Value;
        }

        public String 获取图片内容(String 图片内容地址, bool 获取图片地址_通配符, String 获取图片地址_表达式, bool 获取下页图片_通配符, String 获取下页图片_表达式, String 图片内容过滤)
        {
            页码 = 1;
            String 图片内容 = 获取图片内容(图片内容地址, 获取图片地址_通配符, 获取图片地址_表达式, 获取下页图片_通配符, 获取下页图片_表达式);

            String[] 过滤数组 = 图片内容过滤.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            String[] 图片数组 = 图片内容.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            String 返回值 = "";
            for (int i = 0; i < 图片数组.Length; i++)
                if (!是否匹配图片(图片数组[i], 过滤数组))
                    返回值 += (返回值 == "" ? "" : ",") + 图片数组[i];

            return 返回值;

        }
        private bool 是否匹配图片(String 图片地址, String[] 过滤数组)
        {
            bool 返回值 = false;
            for (int i = 0; i < 过滤数组.Length; i++)
            {
                Regex 表达式 = new Regex(常用.通配符转义(过滤数组[i]), RegexOptions.Singleline);
                if (表达式.IsMatch(图片地址))
                    返回值 = true;
            }
            return 返回值;
        }
        private int 页码;
        private String 获取图片内容(String 图片内容地址, bool 获取图片地址_通配符, String 获取图片地址_表达式, bool 获取下页图片_通配符, String 获取下页图片_表达式)
        {
            if (页码 > 100)
                throw new Exception("死循环");
            String 内容 = 获取网页内容(图片内容地址);
            Regex 表达式 = new Regex(获取图片地址_通配符 ? 常用.通配符转义(获取图片地址_表达式) : 获取图片地址_表达式);
            MatchCollection 所有匹配 = 表达式.Matches(内容);
            if (所有匹配.Count < 1)
                return "";

            String 返回值 = "";
            for (int i = 0; i < 所有匹配.Count; i++)
            {
                Match 匹配 = 所有匹配[i];
                返回值 += 返回值 == "" ? "" : ",";
                返回值 += 处理地址(图片内容地址, HttpUtility.HtmlDecode(匹配.Groups["图片地址"].Value));
            }

            表达式 = new Regex(获取下页图片_通配符 ? 常用.通配符转义(获取下页图片_表达式.Replace("#页码#", (页码 + 1).ToString())) : 获取下页图片_表达式.Replace("#页码#", (页码 + 1).ToString()));
            所有匹配 = 表达式.Matches(内容);
            if (所有匹配.Count < 1)
                return 返回值;

            String 下页地址 = HttpUtility.HtmlDecode(所有匹配[0].Groups["下页地址"].Value);

            if (下页地址 != "")
            {
                页码++;
                下页地址 = 处理地址(图片内容地址, 下页地址);
                String 下页图片=获取图片内容(下页地址,
                    获取图片地址_通配符,
                    获取图片地址_表达式,
                    获取下页图片_通配符,
                    获取下页图片_表达式);
                if (下页图片 != "")
                {
                    返回值 += 返回值 == "" ? "" : ",";
                    返回值 += 下页图片;
                }
            }

            return 返回值;
        }
    }
}