威尼斯人线上娱乐

【威尼斯人线上娱乐】爬虫学习笔记

18 4月 , 2019  

     
最近在做爬虫的学业,今日上学的剧情是关于DNS解析模块的创设的。使用的库为A大切诺基Soft.Tools.Net,它是叁个百般壮大的开源DNS控件库,包括.Net
SPF validation, SenderID validation以及DNS Client、DNS
Server接口。使用该接口可轻易完成DNS客户请求端及服务器解析端。

花色地址:,

Nuget包地址:。

率先引进Nuget包:

 

Install-Package ARSoft.Tools.Net

 

 

上面发轫具体实现:

/// <summary>
/// DNS解析
/// </summary>
/// <param name="dnsServer">DNS服务器IP</param>
/// <param name="timeOut">解析超时时间</param>
/// <param name="url">解析网址</param>
/// <param name="isSuccess">是否解析成功</param>
/// <returns>解析到的IP信息</returns>
public static IPAddress DnsResolver(string dnsServer, int timeOut, string url, out bool isSuccess)
{
    //初始化DnsClient,第一个参数为DNS服务器的IP,第二个参数为超时时间
    var dnsClient = new DnsClient(IPAddress.Parse(dnsServer), timeOut);
    //解析域名。将域名请求发送至DNS服务器解析,第一个参数为需要解析的域名,第二个参数为
    //解析类型, RecordType.A为IPV4类型
    //DnsMessage dnsMessage = dnsClient.Resolve("www.sina.com", RecordType.A);
    var s = new Stopwatch();
    s.Start();
    var dnsMessage = dnsClient.Resolve(DomainName.Parse(url));
    s.Stop();
    Console.WriteLine(s.Elapsed.Milliseconds);
    //若返回结果为空,或者存在错误,则该请求失败。
    if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
    {
        isSuccess= false;
    }
    //循环遍历返回结果,将返回的IPV4记录添加到结果集List中。
    if (dnsMessage != null)
        foreach (var dnsRecord in dnsMessage.AnswerRecords)
        {
            var aRecord = dnsRecord as ARecord;
            if (aRecord == null) continue;
            isSuccess = true;
            return aRecord.Address;
        }
    isSuccess= false;
    return null;
}

调用方法:

bool isSuccess;
IPAddress ip = DnsResolver("223.5.5.5", 200, "shaoweicloud.cn", out isSuccess);
if (isSuccess)
    Console.WriteLine(ip);

 

     
近期在做爬虫的课业,前日学习的剧情是关于DNS解析模块的成立的。使用的库为A福特ExplorerSoft.Tools.Net,它是多少个那多个有力的开源DNS控件库,蕴涵.Net
SPF validation, SenderID validation以及DNS Client、DNS
Server接口。使用该接口可轻便达成DNS客户请求端及服务器解析端。

品种地址:,

Nuget包地址:。

第3引进Nuget包:

 

Install-Package ARSoft.Tools.Net

 

 

下面开头实际落到实处:

/// <summary>
/// DNS解析
/// </summary>
/// <param name="dnsServer">DNS服务器IP</param>
/// <param name="timeOut">解析超时时间</param>
/// <param name="url">解析网址</param>
/// <param name="isSuccess">是否解析成功</param>
/// <returns>解析到的IP信息</returns>
public static IPAddress DnsResolver(string dnsServer, int timeOut, string url, out bool isSuccess)
{
    //初始化DnsClient,第一个参数为DNS服务器的IP,第二个参数为超时时间
    var dnsClient = new DnsClient(IPAddress.Parse(dnsServer), timeOut);
    //解析域名。将域名请求发送至DNS服务器解析,第一个参数为需要解析的域名,第二个参数为
    //解析类型, RecordType.A为IPV4类型
    //DnsMessage dnsMessage = dnsClient.Resolve("www.sina.com", RecordType.A);
    var s = new Stopwatch();
    s.Start();
    var dnsMessage = dnsClient.Resolve(DomainName.Parse(url));
    s.Stop();
    Console.WriteLine(s.Elapsed.Milliseconds);
    //若返回结果为空,或者存在错误,则该请求失败。
    if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
    {
        isSuccess= false;
    }
    //循环遍历返回结果,将返回的IPV4记录添加到结果集List中。
    if (dnsMessage != null)
        foreach (var dnsRecord in dnsMessage.AnswerRecords)
        {
            var aRecord = dnsRecord as ARecord;
            if (aRecord == null) continue;
            isSuccess = true;
            return aRecord.Address;
        }
    isSuccess= false;
    return null;
}

【威尼斯人线上娱乐】爬虫学习笔记。调用方法:

bool isSuccess;
IPAddress ip = DnsResolver("223.5.5.5", 200, "shaoweicloud.cn", out isSuccess);
if (isSuccess)
    Console.WriteLine(ip);

 

     
此前我们已经依照ARSoft.Tools.Net简单的说达成了DNS解析模块的作用,不过当品质要求进步时,每2次爬取都要实行DNS请求,甚至很有极大恐怕一段时间内每一回请求的都以平等的位置,频仍的DNS请求就会化为质量瓶颈,所以大家要经过缓存机制将DNS解析结果缓存下来,下落DNS解析操作,进步系统个性。

如此,我们依照此前封装的MemoryCacheHelper类对DnsResolver类进行改建:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using ARSoft.Tools.Net;
using ARSoft.Tools.Net.Dns;
using Mem = Crawler.Common.MemoryCacheHelper;

namespace Crawler.Protocol
{
public class DnsResolver
{
public TimeSpan TimeSpan { get; set; }
public string Url { get; set; }
public ARecord Record { get; set; }
public string DnsServer { get; set; }
public int TimeOut { get; set; }
public ReturnCode ReturnCode { get; set; }
public bool IsSuccess { get; private set; }
public TimeSpan TimeToLive { get; set; }
public DnsResolver(string url, string dnsServer = “223.5.5.5”, int timeOut = 10000)
{
Url = url;
DnsServer = dnsServer;
TimeOut = timeOut;
IsSuccess = false;
if (Mem.Contains(url))
Fill(Mem.Get(url));
else
Dig();
}

private void Fill(DnsResolver resolver)
{
TimeSpan = resolver.TimeSpan;
Url = resolver.Url;
Record = resolver.Record;
DnsServer = resolver.DnsServer;
TimeOut = resolver.TimeOut;
ReturnCode = resolver.ReturnCode;
IsSuccess = resolver.IsSuccess;
}

public void Dig()
{
//开首化DnsClient,第二个参数为DNS服务器的IP,第①个参数为超时时间
var dnsClient = new DnsClient(IPAddress.Parse(DnsServer), 提姆eOut);
var s = new Stopwatch();
s.Start();
//解析域名。将域名请求发送至DNS服务器解析,参数为索要分析的域名
var dnsMessage = dnsClient.Resolve(DomainName.Parse(Url));
s.Stop();
TimeSpan = s.Elapsed;
//若再次来到结果为空,或许存在漏洞非常多,则该请求失利。
if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
IsSuccess = false;
//循环遍历再次来到结果,将回到的IPV四笔录增添到结果集List中。
if (dnsMessage != null)
{
if (dnsMessage.AnswerRecords.Count > 0)
{
Record = dnsMessage.AnswerRecords[0] as ARecord;
if (Record != null)
{
IsSuccess = true;
TimeToLive=new TimeSpan(0,0,Record.TimeToLive);
Mem.Add(Url, this, TimeToLive);
}
}
}
if (dnsMessage != null) ReturnCode = dnsMessage.ReturnCode;
}
}
}

那般,每一回做完DNS解析后,会依据域名的TTL将分析结果缓存下来,下次询问时得以直接调用缓存,提升系统特性。

0.什么是Redis

Redis是二个开源的应用ANSI
C言语编写、协理互联网、可根据内部存储器亦可持久化的日志型、Key-Value数据库威尼斯人线上娱乐,,并提供各种语言的API

—维基百科

1.与其余用户状态保存方案比较

style=”color: #000000;”>一般开垦中用户处境使用session只怕cookie,三种办法各类利弊。

style=”color: #000000;”>Session:在InProc方式下轻易丢失,并且引起并发难点。若是运用SQLServer或许SQLServer格局又费用了质量

style=”color: #000000;”>Cookie则轻巧将1部分用户音信揭示,加解密同样也消耗了品质。

Redis选用那样的方案消除了多少个难点,

壹.Redis存取速度快。

2.用户数量不轻易遗失。

三.用户多的景况下轻便协理集群。

四.能够查阅在线用户。

5.可见落实用户壹处登六。(通过代码达成,后续介绍)

陆.补助持久化。(当然大概没什么用)

贰.落到实处思路

style=”color: #000000;”>一.我们知道session其实是在cookie中保留了贰个sessionid,用户每便访问都将sessionid发给服务器,服务器通过ID查找用户对应的处境数据。

style=”color: #000000;”>在此处笔者的处理格局也是在cookie中定义一个sessionid,先后要求获得用户情形时将sessionid做为key在Redis中搜索。

style=”color: #000000;”>贰.同时session协助用户在任其自然时间不访问将session回收。

style=”color: #000000;”>借用Redis中Keys帮衬过期时光的特点帮助那一个作用,不过在续期方面供给程序机动拦截请求调用那些艺术(demo有例子)

上边开始代码表达

3.Redis调用接口

先是引述ServiceStack相关DLL。

style=”color: #000000;”>在web.config增多布署,这一个布局用来设置Redis调用地址每台服务用【,】隔绝。主机写在首先位

 

    1 <appSettings>
    2 
    3     <!--每台Redis之间用,分割.第一个必须为主机-->
    4     <add key="SessionRedis" value="127.0.0.1:6384,127.0.0.1:6384"/>
    5 
    6 </appSettings>

开头化配置

static Managers()
{
string sessionRedis= ConfigurationManager.AppSettings[“SessionRedis”];
string timeOut = ConfigurationManager.AppSettings[“SessionRedisTimeOut”];

if (string.IsNullOrEmpty(sessionRedis))
{
throw new Exception(“web.config 缺乏配置SessionRedis,每台Redis之间用,分割.第一个必须为主机”);
}

if (string.IsNullOrEmpty(timeOut)==false)
{
TimeOut = Convert.ToInt32(timeOut);
}

var host = sessionRedis.Split(char.Parse(“,”));
var writeHost = new string[] { host[0] };
var readHosts = host.Skip(1).ToArray();

ClientManagers = new PooledRedisClientManager(writeHost, readHosts, new RedisClientManagerConfig
{
马克斯WritePoolSize = writeReadCount,//“写”链接池链接数
马克斯ReadPoolSize = writeReadCount,//“读”链接池链接数
AutoStart = true
});
}

为了垄断有益写了二个委托

///

/// 写入
///

///
/// ///
public F TryRedisWrite(Func doWrite)
{
PooledRedisClientManager prcm = new Managers().GetClientManagers();
IRedisClient client = null;
try
{
using (client = prcm.GetClient())
{
return doWrite(client);
}
}
catch (RedisException)
{
throw new Exception(“Redis写入极度.Host:” + client.Host + “,Port:” + client.Port);
}
finally
{
if (client != null)
{
client.Dispose();
}
}
}

叁个调用的事例别的的现实性看源码

///

/// 以Key/Value的形式存储对象到缓存中
///

/// 对象类别
/// 要写入的集合 public void KSet(Dictionary value)
{
Func fun = (IRedisClient client) =>
{
client.SetAll(value);
return true;
};

TryRedisWrite(fun);
}

4.实现Session

按下边说的给cookie写三个sessionid

///

/// 用户状态管理
///

public class Session
{
///

/// 初始化
///

/// public Session(HttpContextBase _context)
{
var context = _context;
var cookie = context.Request.Cookies.Get(SessionName);
if (cookie == null || string.IsNullOrEmpty(cookie.Value))
{
SessionId = NewGuid();
context.Response.Cookies.Add(new HttpCookie(SessionName, SessionId));
context.Request.Cookies.Add(new HttpCookie(SessionName, SessionId));
}
else
{
SessionId = cookie.Value;
}
}

}

去存取用户的措施

///

/// 获取当前用户信息
///

///
///
public object Get() where T:class,new()
{
return new RedisClient().KGet(SessionId);
}

///

/// 用户是否在线
///

///
public bool IsLogin()
{
return new RedisClient().KIsExist(SessionId);
}

///

/// 登录
///

///
/// public void Login(T obj) where T : class,new()
{
new RedisClient().KSet(SessionId, obj, new TimeSpan(0, Managers.TimeOut, 0));
}

6.续期

私下认可用户没访问领先三十几分钟注销用户的记名状态,所以用户每一回访问都要将用户的吊销时间推迟二二十一分钟

这亟需调用Redis的续期方法

///

/// 延期
///

/// /// public void KSetEntryIn(string key, TimeSpan expiresTime)
{
Func fun = (IRedisClient client) =>
{
client.ExpireEntryIn(key, expiresTime);
return false;
};

TryRedisWrite(fun);
}

封装今后

///

/// 续期
///

public void Postpone()
{
new RedisClient().KSetEntryIn(SessionId, new TimeSpan(0, Managers.TimeOut, 0));
}

这里自个儿利用了MVC3中的ActionFilter,拦截用户的兼具请求

namespace Test
{
public class SessionFilterAttribute : ActionFilterAttribute
{
///

/// 每次请求都续期
///

/// public override void OnActionExecuting(ActionExecutingContext filterContext)
{
new Session(filterContext.HttpContext).Postpone();
}
}
}

在Global.asax中要注册一下

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new SessionFilterAttribute());
}

protected void Application_Start()
{
RegisterGlobalFilters(GlobalFilters.Filters);
}

5.调用艺术

为了便于调用借用四.0中的新个性,把Controller增加三个扩张属性

public static class ExtSessions
{public static Session SessionExt(this Controller controller)
{
return new Session(controller.HttpContext);
}
}

调用方法

public class HomeController : Controller
{
public ActionResult Index()
{
this.SessionExt().IsLogin();
return View();
}
}

6.代码下载

点击下载

7.后续

SessionManager包涵 获取用户列表数量,注销有些用户,遵照用户ID获取用户音信,在线用户对象列表,在线用户SessionId列表等办法

 

 

 

 

 

懂的施用方法后大家得以对它做尤其封装,得到DnsResolver类:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using ARSoft.Tools.Net;
using ARSoft.Tools.Net.Dns;

namespace Crawler.Protocol
{
public class DnsResolver
{
public TimeSpan TimeSpan { get; set; }
public string Url { get; set; }
public List Record { get; set; }
public string DnsServer { get; set; }
public int TimeOut { get; set; }
public ReturnCode ReturnCode { get; set; }
public bool IsSuccess { get; private set; }
public DnsResolver(string url, string dnsServer = “223.5.5.5”, int timeOut = 200)
{
Url = url;
DnsServer = dnsServer;
TimeOut = timeOut;
Record=new List();
Dig();
}

public void Dig()
{
//初阶化DnsClient,第多个参数为DNS服务器的IP,第三个参数为超时时间
var dnsClient = new DnsClient(IPAddress.Parse(DnsServer), 提姆eOut);
var s = new Stopwatch();
s.Start();
//解析域名。将域名请求发送至DNS服务器解析,参数为索要分析的域名
var dnsMessage = dnsClient.Resolve(DomainName.Parse(Url));
s.Stop();
TimeSpan = s.Elapsed;
//若重临结果为空,或然存在破绽百出,则该请求战败。
if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
IsSuccess = false;
//循环遍历重返结果,将回来的IPV肆笔录增多到结果集List中。
if (dnsMessage != null)
foreach (var dnsRecord in dnsMessage.AnswerRecords)
{
var aRecord = dnsRecord as ARecord;
if (aRecord == null) continue;
IsSuccess = true;
Record.Add(aRecord);
}
if (dnsMessage != null) ReturnCode = dnsMessage.ReturnCode;
}
}
}

调用方法:

DnsResolver dns = new DnsResolver("shaoweicloud.cn");
if (dns.IsSuccess)
    Console.WriteLine(dns.Record[0]);

 

        
至此,DNS解析模块就大旨竣工了,至于为啥标题中标注了半成品,是因为本人想在主导的DNS解析功用的底蕴上依据分析到DNS消息中的TTL做一套音讯缓存机制,减少不要求的双重查询,最近还在思量接纳何种措施,后续达成会更新。

懂的应用方法后大家能够对它做越发封装,得到DnsResolver类:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using ARSoft.Tools.Net;
using ARSoft.Tools.Net.Dns;

namespace Crawler.Protocol
{
public class DnsResolver
{
public TimeSpan TimeSpan { get; set; }
public string Url { get; set; }
public List Record { get; set; }
public string DnsServer { get; set; }
public int TimeOut { get; set; }
public ReturnCode ReturnCode { get; set; }
public bool IsSuccess { get; private set; }
public DnsResolver(string url, string dnsServer = “223.5.5.5”, int timeOut = 200)
{
Url = url;
DnsServer = dnsServer;
TimeOut = timeOut;
Record=new List();
Dig();
}

public void Dig()
{
//开头化DnsClient,第一个参数为DNS服务器的IP,首个参数为超时时间
var dnsClient = new DnsClient(IPAddress.Parse(DnsServer), TimeOut);
var s = new Stopwatch();
s.Start();
//解析域名。将域名请求发送至DNS服务器解析,参数为索要分析的域名
var dnsMessage = dnsClient.Resolve(DomainName.Parse(Url));
s.Stop();
TimeSpan = s.Elapsed;
//若再次回到结果为空,只怕存在张冠李戴,则该请求失利。
if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
IsSuccess = false;
//循环遍历重临结果,将赶回的IPV四记下增加到结果集List中。
if (dnsMessage != null)
foreach (var dnsRecord in dnsMessage.AnswerRecords)
{
var aRecord = dnsRecord as ARecord;
if (aRecord == null) continue;
IsSuccess = true;
Record.Add(aRecord);
}
if (dnsMessage != null) ReturnCode = dnsMessage.ReturnCode;
}
}
}

调用方法:

DnsResolver dns = new DnsResolver("shaoweicloud.cn");
if (dns.IsSuccess)
    Console.WriteLine(dns.Record[0]);

 

        
至此,DNS解析模块就基本告竣了,至于何以标题中标注了半成品,是因为自个儿想在基本的DNS解析效能的功底上依照分析到DNS音信中的TTL做壹套音信缓存机制,收缩不须求的再次查询,近日还在设想使用何种方法,后续完毕会更新。


发表评论

电子邮件地址不会被公开。 必填项已用*标注