原文 C#制作多线程处理强化版网络爬虫

上次做了一个帮公司妹子做了爬虫,不是很精致,这次公司项目里要用到,于是有做了一番修改,功能添加了网址图片采集,下载,线程处理界面网址图片下载等。

说说思路:首相获取初始网址的所有内容 在初始网址采集图片 去初始网址采集链接 把采集到的链接放入队列 继续采集图片,然后继续采集链接,无限循环

还是上图片大家看一下:

处理网页内容抓取跟网页网址爬取都做了改进,下面还是大家来看看代码,有不足之处,还请之处!

网页内容抓取HtmlCodeRequest,

网页网址爬取GetHttpLinks,用正则去筛选html中的Links

图片抓取GetHtmlImageUrlList,用正则去筛选html中的Img

都写进了一个封装类里面 HttpHelper

 /// <summary>
/// 取得HTML中所有图片的 URL。
/// </summary>
/// <param name="sHtmlText">HTML代码</param>
/// <returns>图片的URL列表</returns>
public static string HtmlCodeRequest(string Url)
{
if (string.IsNullOrEmpty(Url))
{
return "";
}
try
{
//创建一个请求
HttpWebRequest httprequst = (HttpWebRequest)WebRequest.Create(Url);
//不建立持久性链接
httprequst.KeepAlive = true;
//设置请求的方法
httprequst.Method = "GET";
//设置标头值
httprequst.UserAgent = "User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705";
httprequst.Accept = "*/*";
httprequst.Headers.Add("Accept-Language", "zh-cn,en-us;q=0.5");
httprequst.ServicePoint.Expect100Continue = false;
httprequst.Timeout = ;
httprequst.AllowAutoRedirect = true;//是否允许302
ServicePointManager.DefaultConnectionLimit = ;
//获取响应
HttpWebResponse webRes = (HttpWebResponse)httprequst.GetResponse();
//获取响应的文本流
string content = string.Empty;
using (System.IO.Stream stream = webRes.GetResponseStream())
{
using (System.IO.StreamReader reader = new StreamReader(stream, System.Text.Encoding.GetEncoding("utf-8")))
{
content = reader.ReadToEnd();
}
}
//取消请求
httprequst.Abort();
//返回数据内容
return content;
}
catch (Exception)
{ return "";
}
}
/// <summary>
/// 提取页面链接
/// </summary>
/// <param name="html"></param>
/// <returns></returns>
public static List<string> GetHtmlImageUrlList(string url)
{
string html = HttpHelper.HtmlCodeRequest(url);
if (string.IsNullOrEmpty(html))
{
return new List<string>();
}
// 定义正则表达式用来匹配 img 标签
Regex regImg = new Regex(@"<img\b[^<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?<imgUrl>[^\s\t\r\n""'<>]*)[^<>]*?/?[\s\t\r\n]*>", RegexOptions.IgnoreCase); // 搜索匹配的字符串
MatchCollection matches = regImg.Matches(html);
List<string> sUrlList = new List<string>(); // 取得匹配项列表
foreach (Match match in matches)
sUrlList.Add(match.Groups["imgUrl"].Value);
return sUrlList;
} /// <summary>
/// 提取页面链接
/// </summary>
/// <param name="html"></param>
/// <returns></returns>
public static List<string> GetHttpLinks(string url)
{
//获取网址内容
string html = HttpHelper.HtmlCodeRequest(url);
if (string.IsNullOrEmpty(html))
{
return new List<string>();
}
//匹配http链接
const string pattern2 = @"http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?";
Regex r2 = new Regex(pattern2, RegexOptions.IgnoreCase);
//获得匹配结果
MatchCollection m2 = r2.Matches(html);
List<string> links = new List<string>();
foreach (Match url2 in m2)
{
if (StringHelper.CheckUrlIsLegal(url2.ToString()) || !StringHelper.IsPureUrl(url2.ToString()) || links.Contains(url2.ToString()))
continue;
links.Add(url2.ToString());
}
//匹配href里面的链接
const string pattern = @"(?i)<a\s[^>]*?href=(['""]?)(?!javascript|__doPostBack)(?<url>[^'""\s*#<>]+)[^>]*>"; ;
Regex r = new Regex(pattern, RegexOptions.IgnoreCase);
//获得匹配结果
MatchCollection m = r.Matches(html);
foreach (Match url1 in m)
{
string href1 = url1.Groups["url"].Value;
if (!href1.Contains("http"))
{
href1 = Global.WebUrl + href1;
}
if (!StringHelper.IsPureUrl(href1) || links.Contains(href1)) continue;
links.Add(href1);
}
return links;
}

这边下载图片有个任务条数限制,限制是200条。如果超过的话线程等待5秒,这里下载图片是异步调用的委托

public string DownLoadimg(string url)
{
if (!string.IsNullOrEmpty(url))
{
try
{
if (!url.Contains("http"))
{
url = Global.WebUrl + url;
}
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Timeout = ;
request.UserAgent = "User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705";
//是否允许302
request.AllowAutoRedirect = true;
WebResponse response = request.GetResponse();
Stream reader = response.GetResponseStream();
//文件名
string aFirstName = Guid.NewGuid().ToString();
//扩展名
string aLastName = url.Substring(url.LastIndexOf(".") + , (url.Length - url.LastIndexOf(".") - ));
FileStream writer = new FileStream(Global.FloderUrl + aFirstName + "." + aLastName, FileMode.OpenOrCreate, FileAccess.Write);
byte[] buff = new byte[];
//实际读取的字节数
int c = ;
while ((c = reader.Read(buff, , buff.Length)) > )
{
writer.Write(buff, , c);
}
writer.Close();
writer.Dispose();
reader.Close();
reader.Dispose();
response.Close();
return (aFirstName + "." + aLastName);
}
catch (Exception)
{
return "错误:地址" + url;
}
}
return "错误:地址为空";
}

话不多说,更多的需要大家自己去改进咯!

C# 多线程网络爬虫的更多相关文章

  1. crawler4j:轻量级多线程网络爬虫实例

    crawler4j是Java实现的开源网络爬虫.提供了简单易用的接口,可以在几分钟内创建一个多线程网络爬虫. 下面实例结合jsoup(中文版API),javacvs 爬取自如租房网(http://sh ...

  2. crawler4j:轻量级多线程网络爬虫

    crawler4j是Java实现的开源网络爬虫.提供了简单易用的接口,可以在几分钟内创建一个多线程网络爬虫. 安装 使用Maven 使用最新版本的crawler4j,在pom.xml中添加如下片段: ...

  3. [原创]一款基于Reactor线程模型的java网络爬虫框架

    AJSprider 概述 AJSprider是笔者基于Reactor线程模式+Jsoup+HttpClient封装的一款轻量级java多线程网络爬虫框架,简单上手,小白也能玩爬虫, 使用本框架,只需要 ...

  4. 网络爬虫(java)

       陆陆续续做了有一个月,期间因为各种技术问题被多次暂停,最关键的一次主要是因为存储容器使用的普通二叉树,在节点权重相同的情况下导致树高增高,在进行遍历的时候效率大大降低,甚至在使用递归的时候导致栈 ...

  5. 开源的49款Java 网络爬虫软件

    参考地址 搜索引擎 Nutch Nutch 是一个开源Java 实现的搜索引擎.它提供了我们运行自己的搜索引擎所需的全部工具.包括全文搜索和Web爬虫. Nutch的创始人是Doug Cutting, ...

  6. [搜片神器]之DHT网络爬虫的C++程序初步开源

    回应大家的要求,特地整理了一开始自己整合的代码,这样最简单,最直接的可以分析流程,至于文章里面提供的程序界面更多,需要大家自己开发. 谢谢园子朋友的支持,已经找到个VPS进行测试,国外的服务器: ht ...

  7. 网络爬虫系统Heritrix的结构分析 (个人读书报告)

      摘要 随着网络时代的日新月异,人们对搜索引擎,网页的内容,大数据处理等问题有了更多的要求.如何从海量的互联网信息中选取最符合要求的信息成为了新的热点.在这种情况下,网络爬虫框架heritrix出现 ...

  8. 一个简单的多线程Python爬虫(一)

    一个简单的多线程Python爬虫 最近想要抓取拉勾网的数据,最开始是使用Scrapy的,但是遇到了下面两个问题: 前端页面是用JS模板引擎生成的 接口主要是用POST提交参数的 目前不会处理使用JS模 ...

  9. 网络爬虫的C++程序

    [搜片神器]之DHT网络爬虫的C++程序初步开源 回应大家的要求,特地整理了一开始自己整合的代码,这样最简单,最直接的可以分析流程,至于文章里面提供的程序界面更多,需要大家自己开发. 谢谢园子朋友的支 ...

随机推荐

  1. Lua 简单的IO交互 和迷宫代码

    function room1 () print("in room1") local move = io.read() if move == "south" th ...

  2. C#和Javascript中 正则表达式使用的总结

    说明:本文并非原创,而是从网站上搜集了一些资料整理的!如有雷同,纯属巧合 1.js中正则表达式的使用 在js中定义正则表达式很简单,有两种方式,一种是通过构造函数,一种是通过//,也就是两个斜杠.例如 ...

  3. 为什么android的R类要定义成16进制

    联想到c语言中的宏定义:我想是一个原因 如: #define SDL_INIT_TIMER 0x00000001 #define SDL_INIT_AUDIO 0x00000010 #define S ...

  4. POJ2251Dungeon Master

    http://poj.org/problem?id=2251 题意 : 就是迷宫升级版,从以前的一个矩阵也就是一层,变为现在的L层," . "是可以走,但是“#”不可以走,从S走到 ...

  5. DataRow.RowState 属性

    RowState 的值取决于两个因素:已对该行执行的操作的类型,以及是否已对 DataRow 调用了 AcceptChanges. private void DemonstrateRowState() ...

  6. MySQL.. ERROR! The server quit without updating PID file问题解决

    不小心将服务器OS给重启了,再启动数据库的时候,出现了很奇怪的问题 [root@dev run]# service mysql restart ERROR! MySQL server PID file ...

  7. Exception in thread "AWT-EventQueue-0" java.lang.IllegalThreadStateException

    在线程中出现这种错误的原因是多次启动start() 解决方法: 将start()改成 run()

  8. lintcode :sort letters by case字符大小写排序

    题目 字符大小写排序 给定一个只包含字母的字符串,按照先小写字母后大写字母的顺序进行排序. 您在真实的面试中是否遇到过这个题? Yes 样例 给出"abAcD",一个可能的答案为& ...

  9. 在PowerDesigner中设计物理模型3——视图、存储过程和函数

    原文:在PowerDesigner中设计物理模型3--视图.存储过程和函数 视图 在SQL Server中视图定义了一个SQL查询,一个查询中可以查询一个表也可以查询多个表,在PD中定义视图与在SQL ...

  10. 【Spring】Redis的两个典型应用场景--good

    原创 BOOT Redis简介 Redis是目前业界使用最广泛的内存数据存储.相比memcached,Redis支持更丰富的数据结构,例如hashes, lists, sets等,同时支持数据持久化. ...