Как мне удалить только тег <body>с сайта? - PullRequest
7 голосов
/ 16 августа 2011

Я работаю над веб-сканером. В настоящий момент я очищаю весь контент, а затем с помощью регулярного выражения удаляю <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;
        }
    }
}

С Page_Load Я вызываю метод scrapeIt(), передавая ему строку, полученную из текстового поля со страницы.

Ответы [ 3 ]

5 голосов
/ 16 августа 2011

По-прежнему самый простой / быстрый (наименее точный) метод.

int start = response.IndexOf("<body", StringComparison.CurrentCultureIgnoreCase);
int end = response.LastIndexOf("</body>", StringComparison.CurrentCultureIgnoreCase);
return response.Substring(start, end-start + "</body>".Length);

Очевидно, что если в теге HEAD есть javascript, например ...

document.write("<body>");

Тогда вы получите чуть больше, чем хотели.

5 голосов
/ 16 августа 2011

Я бы предложил воспользоваться HTML Agility Pack для анализа / манипуляции HTML.

Вы можете легко выбрать тело следующим образом:

var webGet = new HtmlWeb();
var document = webGet.Load(url);
document.DocumentNode.SelectSingleNode("//body")
3 голосов
/ 16 августа 2011

Я думаю, что ваш лучший вариант - использовать легкий анализатор HTML ( что-то вроде Majestic 12 , который, по моим тестам, примерно на 50-100% быстрее, чем HTML Agility Pack), и обрабатывать только узлыкоторый вас интересует (что-нибудь между <body> и </body>).Majestic 12 немного сложнее в использовании, чем HTML Agility Pack, но если вы ищете производительность, то она определенно вам поможет!

Это поможет вам приблизиться к тому, о чем вы просите, но вывсе равно придется скачать всю страницу.Я не думаю, что есть способ обойти это.То, на что вы сэкономите , фактически создаст DOM-узлы для всего остального контента (кроме тела).Вам придется их анализировать, но вы можете пропустить все содержимое узла, который вы не заинтересованы в обработке.

Вот хороший пример использования синтаксического анализатора M12.

У меня нет готового примера того, как захватить тело, но у меня есть один из способов, как захватить только ссылки, и с небольшими изменениями он попадет туда.Вот примерная версия:

GrabBody(ParserTools.OpenM12Parser(_response.BodyBytes));

Вам необходимо открыть анализатор 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;
}

Разбор тела:

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;
        };
    }
}

Сгенерировать узлы DOM сложно, но класс Majestic12ToXml поможет вам сделать это. Как я уже сказал,это ни в коем случае не эквивалентно 3-строчкам, которые вы видели с пакетом гибкости HTML, но как только вы получите инструменты, вы сможете получить именно то, что вам нужно, за небольшую долю затрат на производительность и, возможно, столько же строк кода..

...