Joh*_*cho 7 .net c# html-parsing web-scraping
我正在开发一个webcrawler.目前我刮掉整个内容然后使用正则表达式我删除<meta>, <script>, <style>和其他标签,并获取身体的内容.
但是,我正在尝试优化性能,我想知道是否有一种方法可以只刮掉<body>页面的内容?
namespace WebScrapper
{
public static class KrioScraper
{
public static string scrapeIt(string siteToScrape)
{
string HTML = getHTML(siteToScrape);
string text = stripCode(HTML);
return text;
}
public static string getHTML(string siteToScrape)
{
string response = "";
HttpWebResponse objResponse;
HttpWebRequest objRequest =
(HttpWebRequest) WebRequest.Create(siteToScrape);
objRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; " +
"Windows NT 5.1; .NET CLR 1.0.3705)";
objResponse = (HttpWebResponse) objRequest.GetResponse();
using (StreamReader sr =
new StreamReader(objResponse.GetResponseStream()))
{
response = sr.ReadToEnd();
sr.Close();
}
return response;
}
public static string stripCode(string the_html)
{
// Remove google analytics code and other JS
the_html = Regex.Replace(the_html, "<script.*?</script>", "",
RegexOptions.Singleline | RegexOptions.IgnoreCase);
// Remove inline stylesheets
the_html = Regex.Replace(the_html, "<style.*?</style>", "",
RegexOptions.Singleline | RegexOptions.IgnoreCase);
// Remove HTML tags
the_html = Regex.Replace(the_html, "</?[a-z][a-z0-9]*[^<>]*>", "");
// Remove HTML comments
the_html = Regex.Replace(the_html, "<!--(.|\\s)*?-->", "");
// Remove Doctype
the_html = Regex.Replace(the_html, "<!(.|\\s)*?>", "");
// Remove excessive whitespace
the_html = Regex.Replace(the_html, "[\t\r\n]", " ");
return the_html;
}
}
}
Run Code Online (Sandbox Code Playgroud)
从Page_Load我调用scrapeIt()方法传递给它从页面的文本框中获取的字符串.
我建议利用HTML Agility Pack进行HTML解析/操作.
你可以像这样轻松选择身体:
var webGet = new HtmlWeb();
var document = webGet.Load(url);
document.DocumentNode.SelectSingleNode("//body")
Run Code Online (Sandbox Code Playgroud)
仍然是最简单/最快(最不准确)的方法.
int start = response.IndexOf("<body", StringComparison.CurrentCultureIgnoreCase);
int end = response.LastIndexOf("</body>", StringComparison.CurrentCultureIgnoreCase);
return response.Substring(start, end-start + "</body>".Length);
Run Code Online (Sandbox Code Playgroud)
显然,如果HEAD标签中有javascript,就像......
document.write("<body>");
Run Code Online (Sandbox Code Playgroud)
那么你最终会得到一点你想要的东西.
我认为最好的选择是使用轻量级 HTML 解析器(例如 Majestic 12,根据我的测试,它比 HTML Agility Pack 快大约 50-100%),并且仅处理您感兴趣的节点(介于<body>和</body>)。Majestic 12 比 HTML Agility Pack 稍难使用,但如果您正在寻找性能,那么它肯定会对您有所帮助!
这将使您完成您所要求的内容,但您仍然需要下载整个页面。我认为没有办法解决这个问题。您将节省的实际上是为所有其他内容(除了正文)生成 DOM 节点。您必须解析它们,但您可以跳过您不感兴趣处理的节点的全部内容。
我没有现成的示例来说明如何抓取主体,但我确实有一种如何仅抓取链接的方法,并且只需稍加修改即可到达那里。这是粗略的版本:
GrabBody(ParserTools.OpenM12Parser(_response.BodyBytes));
Run Code Online (Sandbox Code Playgroud)
您需要打开 M12 解析器(M12 附带的示例项目有注释,详细说明了所有这些选项如何影响性能,而且确实如此!!!):
public static HTMLparser OpenM12Parser(byte[] buffer)
{
HTMLparser parser = new HTMLparser();
parser.SetChunkHashMode(false);
parser.bKeepRawHTML = false;
parser.bDecodeEntities = true;
parser.bDecodeMiniEntities = true;
if (!parser.bDecodeEntities && parser.bDecodeMiniEntities)
parser.InitMiniEntities();
parser.bAutoExtractBetweenTagsOnly = true;
parser.bAutoKeepScripts = true;
parser.bAutoMarkClosedTagsWithParamsAsOpen = true;
parser.CleanUp();
parser.Init(buffer);
return parser;
}
Run Code Online (Sandbox Code Playgroud)
解析正文:
public void GrabBody(HTMLparser parser)
{
// parser will return us tokens called HTMLchunk -- warning DO NOT destroy it until end of parsing
// because HTMLparser re-uses this object
HTMLchunk chunk = null;
// we parse until returned oChunk is null indicating we reached end of parsing
while ((chunk = parser.ParseNext()) != null)
{
switch (chunk.oType)
{
// matched open tag, ie <a href="">
case HTMLchunkType.OpenTag:
if (chunk.sTag == "body")
{
// Start generating the DOM node (as shown in the previous example link)
}
break;
// matched close tag, ie </a>
case HTMLchunkType.CloseTag:
break;
// matched normal text
case HTMLchunkType.Text:
break;
// matched HTML comment, that's stuff between <!-- and -->
case HTMLchunkType.Comment:
break;
};
}
}
Run Code Online (Sandbox Code Playgroud)
生成 DOM 节点很棘手,但Majestic12ToXml 类将帮助您做到这一点。正如我所说,这绝不等同于您在 HTML 敏捷包中看到的 3 行代码,但是一旦您掌握了这些工具,您将能够以一小部分性能成本获得所需的内容,并且可能就像很多行代码。
| 归档时间: |
|
| 查看次数: |
2951 次 |
| 最近记录: |