代码优化

啾啾我 2015-09-15 09:43:01

//文件名称
public string FileName = DateTime.Now.ToString("yyyyMMddHHmmssffff");
//count:总数 cg:成功 sb:失败 yc:异常 cf:重复
public int count = 0, cg = 0, sb = 0, yc = 0, cf = 0;
protected void Page_Load(object sender, EventArgs e)
{
DateTime timer = DateTime.Now;//记录此次采集开始计时
ArrayList titleList = GetMainPage();

//创建一个临时表
System.Data.DataTable dt = new System.Data.DataTable("Collecting");
DataColumn dc1 = new DataColumn("Title", System.Type.GetType("System.String"));//标题
DataColumn dc2 = new DataColumn("Price", System.Type.GetType("System.String"));//参考价
DataColumn dc3 = new DataColumn("Contact", System.Type.GetType("System.String"));//联系方式
DataColumn dc4 = new DataColumn("Time", System.Type.GetType("System.String"));//单条采集开始时间
DataColumn dc5 = new DataColumn("Timer", System.Type.GetType("System.String"));//单条采集用时
DataColumn dc6 = new DataColumn("State", System.Type.GetType("System.String"));//采集状态
DataColumn dc7 = new DataColumn("Url", System.Type.GetType("System.String"));//所属url
dt.Columns.Add(dc1);
dt.Columns.Add(dc2);
dt.Columns.Add(dc3);
dt.Columns.Add(dc4);
dt.Columns.Add(dc5);
dt.Columns.Add(dc6);
dt.Columns.Add(dc7);

//读取txt文件的内容
string txtFile = Server.MapPath("~/History/SetRepeatFile.txt");
FileStream fs = new FileStream(txtFile, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs);
string txtFileRead = "";
string txtStr = sr.ReadToEnd();
if (!string.IsNullOrEmpty(txtStr))
txtFileRead = txtStr;
sr.Close();
fs.Close();

string repeat = ""; //为不重复数据设置
count = titleList.Count;//记录全部数据的总数
for (int k = 0; k < count; k++)
{
//用于每条数据采集的用时
DateTime startTime = DateTime.Now;
try
{
string content = GetPage(titleList[k].ToString());//读取网页源代码
string xsState = Regex.Match(content, @"(?<=<span([\s\S]*)class=""pro_center_r""([\s\S]*)>([\s\S]*)销售状态:)(.[^<]*)").Value;
xsState = Regex.Replace(xsState, @"<font(.*)>([^<].+?)", "$2");
if (content == "" || content.IndexOf("该藏不存在") >= 0 || content.Length < 200 || xsState == "已售")
{
sb++;
continue;
}
else
{
DataRow dr = dt.NewRow();
string url = Regex.Match(content, @"(?<=\$\.getJSON\(\"")((?:http:\//usercenter.abc123.com/GetInfo.asp)(?:(?!\"").)*)(?=\"")").Groups[1].Value;
string content2 = GetPage(url);

string contact = Regex.Match(content2, @"(?<=Mobile\""\:(\""))((?:\d)(?:(?!\"").)*)(?=\"",)").Value;
Regex regex = new Regex("^1\\d{10}$");
if (
txtFileRead.IndexOf(contact) < 0 && //禁止已经采集过得号码
repeat.IndexOf(contact) < 0 && //禁止本次已经采集过得号码
!string.IsNullOrEmpty(contact.ToLower()) && //禁止号码为空
regex.IsMatch(contact)//禁止非号码
)
{
repeat += "," + contact;
}
else
{
cf++;
continue;
}
dr["Contact"] = contact;

string title = Regex.Match(content, @"(?<=<div([\s\S]*)id=""pro_title""([\s\S]*)>.*</span>).*(?=[^<])").Value;
title = Regex.Replace(title, @"([\s| |/g])", "");
dr["Title"] = Regex.Match(title, @"(.[^<])*").Value;

string price = Regex.Match(content, @"(?<=>参考价:([\s\S]*)<span([\s\S]*)class=""price"">)([\s\S]+?)(?=<\/span>)").Value;
price = Regex.Replace(price, @"<font(.*)>([^<].+?)</font>", "$2", RegexOptions.IgnoreCase);
price = Regex.Replace(price, @"([\s| |/g])", "");
dr["Price"] = price;
//设置价格大于10万或议价
string priceRen = "";
string priceRep = price.Replace("元", "");
if (Regex.IsMatch(priceRep, @"^\d*$"))
{
if (Convert.ToInt32(priceRep) >= 100000 || Convert.ToInt32(priceRep) <= 50)
priceRen = price;
else
priceRen = "";
}
else if (priceRep == "议价")
priceRen = price;
else
priceRen = "";

dr["Time"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff");
TimeSpan ts = DateTime.Now - DateTime.Now;
dr["Timer"] = ts.Seconds.ToString() + "." + ts.Milliseconds.ToString() + "ms";
dr["State"] = "成功";
dr["Url"] = titleList[k].ToString();

if (priceRen != "")//禁止价格小于10万或非议价
{
dt.Rows.Add(dr);
cg++;
}
else
sb++;
}
}
catch (Exception ex)
{
DAL.ErrorLog.WriteLog(ex);//记录异常信息
yc++;
}
}
if (dt.Rows.Count > 0)
{
//创建Excel文件存放数据
CreateExcelFile(dt);
//写入xml文件作为历史记录
string cTime = timer.ToString();//此次采集时间
string c_count = titleList.Count.ToString();//采集总数
TimeSpan tss = DateTime.Now - timer;
string c_timer = tss.Minutes.ToString() + "." + tss.Seconds.ToString() + "s";
string c_state = "<span>成功" + cg + "</span><span class=\"re\">过滤" + cf + "</span><span class=\"fail\">失败" + sb + "</span><span class=\"ero\">异常" + yc + "</span>";
SetXmlFile(FileName, cTime, c_count, c_timer, c_state);
//把联系方式写入到txt文档(主要是不采集已经采集过的号码数据)
StreamWriter sw = new StreamWriter(txtFile, true);
sw.WriteLine("\r" + DateTime.Now.ToString("yyyy年MM月dd日 HH:mm:ss") + " 采集\r");
sw.WriteLine(repeat.Substring(1));
sw.WriteLine("\n");
sw.Close();

//绑定数据
this.repCollectingList.DataSource = dt;
this.repCollectingList.DataBind();
}
else
Record.InnerHtml = "<p style=\"color:red; text-align:center;\">请检查采集设置,此次没有采集到任何数据哦!</p>";



/// <summary>
/// 获取页面的源代码
/// </summary>
/// <param name="url">定义的url页面</param>
/// <returns></returns>
private static string GetPage(string url)
{
string content = "";
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; .NET CLR 3.5.21022; .NET CLR 1.0.3705; .NET CLR 1.1.4322)";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream hwStream = response.GetResponseStream();
Encoding eData = Encoding.Default; //页面都是gbk编码
StreamReader sData = new StreamReader(hwStream, eData);
content = sData.ReadToEnd();
sData.Close();
}
catch (Exception)
{
content = "";
}
return content;
}



我的代码有没有需要优化的地方,如果采集5k条数据用时要至少30分钟左右,就算是1k条也要用10分钟左右,不知道我的代码有什么不对的地方,请大神给看看(个人网络没有什么问题)。
...全文
168 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
net_xiaojian 2015-09-16
  • 打赏
  • 举报
回复
值得学习! //count:总数 cg:成功 sb:失败 yc:异常 cf:重复 public int count = 0, cg = 0, sb = 0, yc = 0, cf = 0; 这类的定义直接用英文单词了,也不用注释。
啾啾我 2015-09-15
  • 打赏
  • 举报
回复
引用 3 楼 starfd 的回复:
List<string> urls = new List<string>();
int maxTasks = 10;//这并不代表实际就开了10个线程,实际开多少个是由你的ThreadPool.SetMaxThreads,ThreadPool.SetMinThreads决定的
int splitLength = urls.Count / maxTasks;
if (maxTasks % maxTasks != 0)
{
    splitLength++;
}
Parallel.For(0, maxTasks, i =>
{
    for (int j = 0; j < splitLength; j++)
    {
        var idx = j + i * splitLength;
        if (idx >= urls.Count)
        {
            break;
        }
        var url = urls[idx];
        //请求url
    }
});
这个是用Parallel做的例子
谢谢,我了解一下。
啾啾我 2015-09-15
  • 打赏
  • 举报
回复
引用 4 楼 ajianchina 的回复:
用开源的NCrawler项目吧,非常高效的多线程网络爬虫,不仅可以分析处理HTML,还可对Text, PDF, 和IFilter文档进行分析处理。能够很方便抽取、使用和修改信息。 项目地址: http://ncrawler.codeplex.com/ 下载去吧,至少你可以借鉴一下里面设计思路。
感谢,我去了解一下。
ajianchina 2015-09-15
  • 打赏
  • 举报
回复
用开源的NCrawler项目吧,非常高效的多线程网络爬虫,不仅可以分析处理HTML,还可对Text, PDF, 和IFilter文档进行分析处理。能够很方便抽取、使用和修改信息。 项目地址: http://ncrawler.codeplex.com/ 下载去吧,至少你可以借鉴一下里面设计思路。
  • 打赏
  • 举报
回复
List<string> urls = new List<string>();
int maxTasks = 10;//这并不代表实际就开了10个线程,实际开多少个是由你的ThreadPool.SetMaxThreads,ThreadPool.SetMinThreads决定的
int splitLength = urls.Count / maxTasks;
if (maxTasks % maxTasks != 0)
{
    splitLength++;
}
Parallel.For(0, maxTasks, i =>
{
    for (int j = 0; j < splitLength; j++)
    {
        var idx = j + i * splitLength;
        if (idx >= urls.Count)
        {
            break;
        }
        var url = urls[idx];
        //请求url
    }
});
这个是用Parallel做的例子
啾啾我 2015-09-15
  • 打赏
  • 举报
回复
引用 1 楼 starfd 的回复:
你第一段代码是解析,第二段代码是抓取 但两段代码并没有链接的地方,当然也可以猜测出来是抓数据后存入txt文件 然后另一边从txt中读取出来并进行解析 另外你这个慢也是正常的,你都是单线程在做事情,一般爬虫程序都是开多线程的 你可以了解下Task如何用法,如果你的版本低于4.0的话,那就只能用Thread或者ThreadPool了
谢谢提示,我的txt文件主要是做采集的信息不能重复,实际上采集的数据是存放在excel文件中的,有没有比较适合我这个抓取的多线程执行的程序代码,我借鉴一下。感谢
  • 打赏
  • 举报
回复
你第一段代码是解析,第二段代码是抓取 但两段代码并没有链接的地方,当然也可以猜测出来是抓数据后存入txt文件 然后另一边从txt中读取出来并进行解析 另外你这个慢也是正常的,你都是单线程在做事情,一般爬虫程序都是开多线程的 你可以了解下Task如何用法,如果你的版本低于4.0的话,那就只能用Thread或者ThreadPool了

62,074

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧