这是类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HtmlAgilityPack;
using System.Net;
namespace GatherLinks
{
/// <summary>
/// A result encapsulating the Url and the HtmlDocument
/// </summary>
class WebPage
{
public Uri Url { get; set; }
/// <summary>
/// Get every WebPage.Internal on a web site (or part of a web site) visiting all internal links just once
/// plus every external page (or other Url) linked to the web site as a WebPage.External
/// </summary>
/// <remarks>
/// Use .OfType WebPage.Internal to get just the internal ones if that's what you want
/// </remarks>
public static IEnumerable<WebPage> GetAllPagesUnder(Uri urlRoot)
{
var queue = new Queue<Uri>();
var allSiteUrls = new HashSet<Uri>();
queue.Enqueue(urlRoot);
allSiteUrls.Add(urlRoot);
while (queue.Count > 0)
{
Uri url = queue.Dequeue();
HttpWebRequest oReq = (HttpWebRequest)WebRequest.Create(url);
oReq.UserAgent = @"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5";
HttpWebResponse resp = (HttpWebResponse)oReq.GetResponse();
WebPage result;
if (resp.ContentType.StartsWith("text/html", StringComparison.InvariantCultureIgnoreCase))
{
HtmlDocument doc = new HtmlDocument();
try
{
var resultStream = resp.GetResponseStream();
doc.Load(resultStream); // The HtmlAgilityPack
result = new Internal() { Url = url, HtmlDocument = doc };
}
catch (System.Net.WebException ex)
{
result = new WebPage.Error() { Url = url, Exception = ex };
}
catch (Exception ex)
{
ex.Data.Add("Url", url); // Annotate the exception with the Url
throw;
}
// Success, hand off the page
yield return new WebPage.Internal() { Url = url, HtmlDocument = doc };
// And and now queue up all the links on this page
foreach (HtmlNode link in doc.DocumentNode.SelectNodes(@"//a[@href]"))
{
HtmlAttribute att = link.Attributes["href"];
if (att == null) continue;
string href = att.Value;
if (href.StartsWith("javascript", StringComparison.InvariantCultureIgnoreCase)) continue; // ignore javascript on buttons using a tags
Uri urlNext = new Uri(href, UriKind.RelativeOrAbsolute);
// Make it absolute if it's relative
if (!urlNext.IsAbsoluteUri)
{
urlNext = new Uri(urlRoot, urlNext);
}
if (!allSiteUrls.Contains(urlNext))
{
allSiteUrls.Add(urlNext); // keep track of every page we've handed off
if (urlRoot.IsBaseOf(urlNext))
{
queue.Enqueue(urlNext);
}
else
{
yield return new WebPage.External() { Url = urlNext };
}
}
}
}
}
}
///// <summary>
///// In the future might provide all the images too??
///// </summary>
//public class Image : WebPage
//{
//}
/// <summary>
/// Error loading page
/// </summary>
public class Error : WebPage
{
public int HttpResult { get; set; }
public Exception Exception { get; set; }
}
/// <summary>
/// External page - not followed
/// </summary>
/// <remarks>
/// No body - go load it yourself
/// </remarks>
public class External : WebPage
{
}
/// <summary>
/// Internal page
/// </summary>
public class Internal : WebPage
{
/// <summary>
/// For internal pages we load the document for you
/// </summary>
public virtual HtmlDocument HtmlDocument { get; internal set; }
}
}
}
它永远不会停止在这一行:
public Uri Url { get; set; }
并且永远不要停在本课程的任何其他行上。仅当我删除该行时:
public Uri Url { get; set; }
然后它停在其他线路上。但我不明白为什么它会停在第一行?我该如何解决它?
我尝试阅读有关自动属性的信息,但我不明白它是什么,我不想在本课程中使用它。
将断点添加到声明此类的位置。
WebPage wp =new WebPage();
因为正如阿西夫上面所说,它不会止步于宣言。
或者在声明类后设置 Url 变量
wp.Url="blahblahblah.html";
编辑:我不知道断点不适用于自动属性。更改您的
public Uri Url{get;set;}
自
private Uri _Url=new Uri();
public Url URL{get{return _Url;}set{_Url = value;}}
您在这里要做的是创建一个私有变量名称_Url并使用属性 URL 访问它
用途是
Url="blahblahblah";
与您当前使用的相同
自动实现的属性不支持断点。尝试将其设置在GetAllPagesUnder
方法的第一行。
从你的问题来看,这非常模糊 - 但我有一种预感,你正在调用的程序的某个地方:
var results = WebPage.GetAllPagesUnder([some uri]);
您是否希望在调用该方法时命中断点?
它不会 - 它会产生一个枚举器。 在foreach
可枚举项之前,代码实际上不会执行任何操作;或者可能急于通过ToArray
、ToList
或类似的东西加载它。
至于自动属性,不,你不能断点 - 但你永远不需要 - 只需断点设置属性的代码。 如果您确实想要,请坚持使用私有支持字段并手动实现该属性。 如果做不到这一点,请为类提供一个构造函数,该构造函数采用Uri
并设置它,然后改为断点。
Url
属性上设置断点,如此处所述。
设置断点的标准方法不适用于自动属性。