【问题标题】:Can you provide examples of parsing HTML?你能提供解析HTML的例子吗?
【发布时间】:2010-10-20 21:00:42
【问题描述】:

如何使用多种语言和解析库解析 HTML?


回答时:

在回答有关如何使用正则表达式解析 HTML 的问题时,将链接到各个 cmets,以显示正确的做事方式。

为了保持一致性,我要求该示例为锚标记中的href 解析 HTML 文件。为了方便搜索这个问题,我要求您遵循这种格式

语言:[语言名称]

库:[库名称]

[example code]

请将该库设为该库文档的链接。如果您想提供除提取链接以外的示例,还请包括:

目的:[解析的作用]

【问题讨论】:

  • 重复每个示例,HTML builder 代码毫无意义
  • 以及为什么你用毫无意义/无用的使用指令来混淆 perl 代码? (警告和严格)
  • 自包含,工作示例更好。所有 Perl 代码都应该包含严格和警告,它们并非毫无意义;它们是 Modern Perl 的一部分。如果您认为代码“毫无意义”和“无用”,我会不寒而栗。
  • 在我的代码中,我总是使用警告和严格;在 THIS 上下文中,它们毫无意义。这些示例中的大多数都不是“自包含的”(例如 jquery、ruby 和其他答案),那么为什么还要使用基于 perl 的解决方案呢?
  • 因为你可以,而且 JavaScript 示例是自包含在它们的环境中的。我没有更改 nokogiri 示例,因为我无法在我的机器上安装 nokogiri。我不想更改我不理解的代码。但我会改变它;一方面,它看起来不像是在解决这个例子。至于为正在学习的人使用严格的、不安全的代码是一种犯罪行为。他们需要所有能得到的强化。

标签: html language-agnostic html-parsing


【解决方案1】:

语言:JavaScript
图书馆:jQuery

$.each($('a[href]'), function(){
    console.debug(this.href);
});

(使用 firebug console.debug 进行输出...)

并加载任何 html 页面:

$.get('http://stackoverflow.com/', function(page){
     $(page).find('a[href]').each(function(){
        console.debug(this.href);
    });
});

为此使用了另一个 each 函数,我认为链接方法时更简洁。

【讨论】:

  • 好吧,如果你这样看的话。 :) 但是使用 javascript/jquery 来解析 HTML 感觉很自然,非常适合这样的东西。
  • 使用浏览器作为解析器是终极解析器。给定浏览器中的 DOM文档树。
【解决方案2】:

语言:C#
图书馆:HtmlAgilityPack

class Program
{
    static void Main(string[] args)
    {
        var web = new HtmlWeb();
        var doc = web.Load("http://www.stackoverflow.com");

        var nodes = doc.DocumentNode.SelectNodes("//a[@href]");

        foreach (var node in nodes)
        {
            Console.WriteLine(node.InnerHtml);
        }
    }
}

【讨论】:

    【解决方案3】:

    语言:Python
    图书馆:BeautifulSoup

    from BeautifulSoup import BeautifulSoup
    
    html = "<html><body>"
    for link in ("foo", "bar", "baz"):
        html += '<a href="http://%s.com">%s</a>' % (link, link)
    html += "</body></html>"
    
    soup = BeautifulSoup(html)
    links = soup.findAll('a', href=True) # find <a> with a defined href attribute
    print links  
    

    输出:

    [<a href="http://foo.com">foo</a>,
     <a href="http://bar.com">bar</a>,
     <a href="http://baz.com">baz</a>]
    

    也可以:

    for link in links:
        print link['href']
    

    输出:

    http://foo.com
    http://bar.com
    http://baz.com
    

    【讨论】:

    • 这很好,但是 BeautifulSoup 是否提供了一种查看标签以获取属性的方法? 去查看文档
    • 第一个示例中的输出只是匹配链接的文本表示,它们实际上是您可以做各种有趣事情的对象。
    • 是的,我刚刚阅读了文档,您在修复代码方面比我强。我确实添加了 try/catch 以防止它在 href 不存在时爆炸。显然“链接中的'href'”不起作用。
    • 一定要用beautifulsoup crummy.com/software/BeautifulSoup/3.1-problems.html
    【解决方案4】:

    语言:Perl
    图书馆:pQuery

    use strict;
    use warnings;
    use pQuery;
    
    my $html = join '',
        "<html><body>",
        (map { qq(<a href="http://$_.com">$_</a>) } qw/foo bar baz/),
        "</body></html>";
    
    pQuery( $html )->find( 'a' )->each(
        sub {  
            my $at = $_->getAttribute( 'href' ); 
            print "$at\n" if defined $at;
        }
    );
    

    【讨论】:

    【解决方案5】:

    语言:贝壳
    库:lynx(嗯,它不是库,但在 shell 中,每个程序都是某种库)

    lynx -dump -listonly http://news.google.com/
    

    【讨论】:

    • +1 表示尝试,+1 表示可行的解决方案,-1 表示无法推广到其他任务的解决方案:net +1
    • 好吧,任务定义得很好——它必须从“a”标签中提取链接。 :)
    • 是的,但它被定义为一个示例来展示如何解析,我可以很容易地要求您打印具有类“phonenum”的 标记的所有内容。
    • 我同意这对一般问题没有帮助,但具体问题可能是一个受欢迎的问题,所以对我来说,作为特定领域的一种方法似乎是合理的一般问题。
    【解决方案6】:

    语言:Ruby
    图书馆:Hpricot

    #!/usr/bin/ruby
    
    require 'hpricot'
    
    html = '<html><body>'
    ['foo', 'bar', 'baz'].each {|link| html += "<a href=\"http://#{link}.com\">#{link}</a>" }
    html += '</body></html>'
    
    doc = Hpricot(html)
    doc.search('//a').each {|elm| puts elm.attributes['href'] }
    

    【讨论】:

      【解决方案7】:

      语言:Python
      图书馆:HTMLParser

      #!/usr/bin/python
      
      from HTMLParser import HTMLParser
      
      class FindLinks(HTMLParser):
          def __init__(self):
              HTMLParser.__init__(self)
      
          def handle_starttag(self, tag, attrs):
              at = dict(attrs)
              if tag == 'a' and 'href' in at:
                  print at['href']
      
      
      find = FindLinks()
      
      html = "<html><body>"
      for link in ("foo", "bar", "baz"):
          html += '<a href="http://%s.com">%s</a>' % (link, link)
      html += "</body></html>"
      
      find.feed(html)
      

      【讨论】:

        【解决方案8】:

        语言:Perl
        图书馆:HTML::Parser

        #!/usr/bin/perl
        
        use strict;
        use warnings;
        
        use HTML::Parser;
        
        my $find_links = HTML::Parser->new(
            start_h => [
                sub {
                    my ($tag, $attr) = @_;
                    if ($tag eq 'a' and exists $attr->{href}) {
                        print "$attr->{href}\n";
                    }
                }, 
                "tag, attr"
            ]
        );
        
        my $html = join '',
            "<html><body>",
            (map { qq(<a href="http://$_.com">$_</a>) } qw/foo bar baz/),
            "</body></html>";
        
        $find_links->parse($html);
        

        【讨论】:

        • 使用 LWP::Simple 下载此页面(正如我在下面的 perl 示例中所做的那样)表明您找到了没有 href 的 a (但有名称),所以我们只想检查在打印之前有 一个 href。
        【解决方案9】:

        语言 Perl
        图书馆:HTML::LinkExtor

        Perl 的美妙之处在于您拥有用于非常具体任务的模块。比如链接提取。

        整个程序:

        #!/usr/bin/perl -w
        use strict;
        
        use HTML::LinkExtor;
        use LWP::Simple;
        
        my $url     = 'http://www.google.com/';
        my $content = get( $url );
        
        my $p       = HTML::LinkExtor->new( \&process_link, $url, );
        $p->parse( $content );
        
        exit;
        
        sub process_link {
            my ( $tag, %attr ) = @_;
        
            return unless $tag eq 'a';
            return unless defined $attr{ 'href' };
        
            print "- $attr{'href'}\n";
            return;
        }
        

        解释:

        • 使用严格 - 打开“严格”模式 - 简化潜在的调试,而不是完全 与示例相关
        • 使用 HTML::LinkExtor - 加载有趣的模块
        • 使用 LWP::Simple - 只是获取一些用于测试的 html 的简单方法
        • my $url = 'http://www.google.com/' - 我们将从哪个页面提取 url
        • 我的 $content = get( $url ) - 获取页面 html
        • my $p = HTML::LinkExtor->new( \&process_link, $url ) - 创建 LinkExtor 对象,为其提供将用作每个 url 回调的函数的引用,并将 $url 用作相对的 BASEURL网址
        • $p->parse($content) - 我猜很明显
        • 退出 - 程序结束
        • 子 process_link - 函数 process_link 的开始
        • my ($tag, %attr) - 获取参数,即标签名称及其属性
        • return unless $tag eq 'a' - 如果标签不是
        • 则跳过处理
        • 除非定义否则返回 $attr{'href'} - 如果 标记没有 href 属性则跳过处理
        • 打印“-$attr{'href'}\n”; - 我猜很明显:)
        • 返回; - 完成功能

        就是这样。

        【讨论】:

        • 很好,但我认为您错过了问题的重点,示例在那里是为了使代码相似,而不是因为我想要链接。用更一般的术语来思考。目标是为人们提供使用解析器而不是正则表达式的工具。
        • 我可能遗漏了一些东西,但我在问题描述中读到:“为了保持一致性,我要求该示例为锚标记中的 href 解析 HTML 文件。”如果您要求例如解析 标签 - 我可能会使用 HTML::TableExtract - 基本上 - 专用工具胜过(在我看来)通用工具。
        • 好的,找到类为“learn”的div标签内的所有类“to_understand_intent”的span标签。专门的工具很棒,但它们就是:专门的。有一天,您最终会需要了解通用工具。这是关于通用工具的问题,而不是使用这些工具的专用库。
        • 对于这个新请求 - 当然 HTML::Parser 会好得多。但是仅仅说“使用 HTML::Parser”是完全错误的。应该为给定的任务使用适当的工具。对于提取href,我会说使用HTML::Parser 太过分了。用于提取 s - 也是如此。问“给我解析...的一般方法”是错误的,因为它假设存在 1 个工具(语言中)对所有情况都是完美的。我个人至少以 6 种不同的方式解析 HTML,具体取决于我需要做什么。
        • 再看任务。该任务不是获取 HTMl 页面中的链接,而是使用获取 HTML 页面中的链接作为示例来演示您最喜欢的解析器是如何工作的。之所以选择它,是因为它是一项简单的任务,需要找到正确的标签并查看其中的一段数据。之所以选择它,也是因为它是一项常见任务。因为这是 Perl 为您自动完成的一项常见任务,但这并不意味着这个问题要求您提供自动答案。
        【解决方案10】:

        语言:红宝石
        图书馆:Nokogiri

        #!/usr/bin/env ruby
        require 'nokogiri'
        require 'open-uri'
        
        document = Nokogiri::HTML(open("http://google.com"))
        document.css("html head title").first.content
        => "Google"
        document.xpath("//title").first.content
        => "Google"
        

        【讨论】:

          【解决方案11】:

          语言:通用 Lisp
          图书馆:Closure HtmlClosure XmlCL-WHO

          (使用 DOM API 显示,不使用 XPATH 或 STP API)

          (defvar *html*
            (who:with-html-output-to-string (stream)
              (:html
               (:body (loop
                         for site in (list "foo" "bar" "baz")
                         do (who:htm (:a :href (format nil "http://~A.com/" site))))))))
          
          (defvar *dom*
            (chtml:parse *html* (cxml-dom:make-dom-builder)))
          
          (loop
             for tag across (dom:get-elements-by-tag-name *dom* "a")
             collect (dom:get-attribute tag "href"))
          => 
          ("http://foo.com/" "http://bar.com/" "http://baz.com/")
          

          【讨论】:

          • 是否 collect 或 dom:get-attribute 正确处理未设置 href 的标签?
          • 取决于正确性的定义。在显示的示例中,将为没有“href”属性的“a”标签收集空字符串。如果循环被重写为 (loop for tag across (dom:get-elements-by-tag-name dom "a") when (string/= (dom:get-attribute tag "href") "") collect (dom:get-attribute tag "href")) 那么只会收集非空的 "href"。
          • 其实不是when (string/= (dom:get-attribute tag "href") "") 而是when (dom:has-attribute tag "href")
          • 没有循环宏你会怎么做?
          【解决方案12】:

          语言:Clojure
          库:Enlive(Clojure 的基于选择器(à la CSS)的模板和转换系统)


          选择器表达式:

          (def test-select
               (html/select (html/html-resource (java.io.StringReader. test-html)) [:a]))
          

          现在我们可以在 REPL 中执行以下操作(我在 test-select 中添加了换行符):

          user> test-select
          ({:tag :a, :attrs {:href "http://foo.com/"}, :content ["foo"]}
           {:tag :a, :attrs {:href "http://bar.com/"}, :content ["bar"]}
           {:tag :a, :attrs {:href "http://baz.com/"}, :content ["baz"]})
          user> (map #(get-in % [:attrs :href]) test-select)
          ("http://foo.com/" "http://bar.com/" "http://baz.com/")
          

          您需要以下内容才能试用:

          序言:

          (require '[net.cgrand.enlive-html :as html])
          

          测试 HTML:

          (def test-html
               (apply str (concat ["<html><body>"]
                                  (for [link ["foo" "bar" "baz"]]
                                    (str "<a href=\"http://" link ".com/\">" link "</a>"))
                                  ["</body></html>"])))
          

          【讨论】:

          • 不确定我是否将 Enlive 称为“解析器”,但我肯定会用它来代替它,所以——这里有一个例子。
          【解决方案13】:

          语言:Perl
          图书馆:XML::Twig

          #!/usr/bin/perl
          use strict;
          use warnings;
          use Encode ':all';
          
          use LWP::Simple;
          use XML::Twig;
          
          #my $url = 'http://stackoverflow.com/questions/773340/can-you-provide-an-example-of-parsing-html-with-your-favorite-parser';
          my $url = 'http://www.google.com';
          my $content = get($url);
          die "Couldn't fetch!" unless defined $content;
          
          my $twig = XML::Twig->new();
          $twig->parse_html($content);
          
          my @hrefs = map {
              $_->att('href');
          } $twig->get_xpath('//*[@href]');
          
          print "$_\n" for @hrefs;
          

          警告:像这样的页面可能会出现宽字符错误(将 url 更改为被注释掉的页面会出现此错误),但上面的 HTML::Parser 解决方案不存在此问题。

          【讨论】:

          • 很好,我一直在使用 XML::Twig,但从未意识到有 parse_html 方法。
          【解决方案14】:

          【讨论】:

            【解决方案15】:

            语言:Java
            库:XOMTagSoup

            我在此示例中故意包含格式错误且不一致的 XML。

            import java.io.IOException;
            
            import nu.xom.Builder;
            import nu.xom.Document;
            import nu.xom.Element;
            import nu.xom.Node;
            import nu.xom.Nodes;
            import nu.xom.ParsingException;
            import nu.xom.ValidityException;
            
            import org.ccil.cowan.tagsoup.Parser;
            import org.xml.sax.SAXException;
            
            public class HtmlTest {
                public static void main(final String[] args) throws SAXException, ValidityException, ParsingException, IOException {
                    final Parser parser = new Parser();
                    parser.setFeature(Parser.namespacesFeature, false);
                    final Builder builder = new Builder(parser);
                    final Document document = builder.build("<html><body><ul><li><a href=\"http://google.com\">google</li><li><a HREF=\"http://reddit.org\" target=\"_blank\">reddit</a></li><li><a name=\"nothing\">nothing</a><li></ul></body></html>", null);
                    final Element root = document.getRootElement();
                    final Nodes links = root.query("//a[@href]");
                    for (int linkNumber = 0; linkNumber < links.size(); ++linkNumber) {
                        final Node node = links.get(linkNumber);
                        System.out.println(((Element) node).getAttributeValue("href"));
                    }
                }
            }
            

            TagSoup 默认为文档添加一个引用 XHTML 的 XML 命名空间。我选择在这个示例中抑制它。使用默认行为需要调用root.query 来包含这样的命名空间:

            root.query("//xhtml:a[@href]", new nu.xom.XPathContext("xhtml", root.getNamespaceURI())
            

            【讨论】:

            • 我相信两者都可以正常工作。 TagSoup 可以解析任何你可以扔给它的东西。
            【解决方案16】:

            语言:C#
            库:System.XML(标准 .NET)

            using System.Collections.Generic;
            using System.Xml;
            
            public static void Main(string[] args)
            {
                List<string> matches = new List<string>();
            
                XmlDocument xd = new XmlDocument();
                xd.LoadXml("<html>...</html>");
            
                FindHrefs(xd.FirstChild, matches);
            }
            
            static void FindHrefs(XmlNode xn, List<string> matches)
            {
                if (xn.Attributes != null && xn.Attributes["href"] != null)
                    matches.Add(xn.Attributes["href"].InnerXml);
            
                foreach (XmlNode child in xn.ChildNodes)
                    FindHrefs(child, matches);
            }
            

            【讨论】:

            • 如果 HTML 不是有效的 xml(例如未封闭的 img 标签),这会起作用吗?
            【解决方案17】:

            语言:PHP
            库:SimpleXML(和 DOM)

            <?php
            $page = new DOMDocument();
            $page->strictErrorChecking = false;
            $page->loadHTMLFile('http://stackoverflow.com/questions/773340');
            $xml = simplexml_import_dom($page);
            
            $links = $xml->xpath('//a[@href]');
            foreach($links as $link)
                echo $link['href']."\n";
            

            【讨论】:

              【解决方案18】:

              语言:JavaScript
              图书馆:DOM

              var links = document.links;
              for(var i in links){
                  var href = links[i].href;
                  if(href != null) console.debug(href);
              }
              

              (使用 firebug console.debug 进行输出...)

              【讨论】:

                【解决方案19】:

                语言:Racket

                库:(planet ashinn/html-parser:1)(planet clements/sxml2:1)

                (require net/url
                         (planet ashinn/html-parser:1)
                         (planet clements/sxml2:1))
                
                (define the-url (string->url "http://stackoverflow.com/"))
                (define doc (call/input-url the-url get-pure-port html->sxml))
                (define links ((sxpath "//a/@href/text()") doc))
                

                以上示例使用来自新包系统的包:html-parsingsxml

                (require net/url
                         html-parsing
                         sxml)
                
                (define the-url (string->url "http://stackoverflow.com/"))
                (define doc (call/input-url the-url get-pure-port html->xexp))
                (define links ((sxpath "//a/@href/text()") doc))
                

                注意:从命令行使用“raco”安装所需的软件包,使用:

                raco pkg install html-parsing
                

                和:

                raco pkg install sxml
                

                【讨论】:

                  【解决方案20】:

                  语言:Python
                  图书馆:lxml.html

                  import lxml.html
                  
                  html = "<html><body>"
                  for link in ("foo", "bar", "baz"):
                      html += '<a href="http://%s.com">%s</a>' % (link, link)
                  html += "</body></html>"
                  
                  tree = lxml.html.document_fromstring(html)
                  for element, attribute, link, pos in tree.iterlinks():
                      if attribute == "href":
                          print link
                  

                  lxml 也有一个 CSS 选择器类用于遍历 DOM,这使得使用它与使用 JQuery 非常相似:

                  for a in tree.cssselect('a[href]'):
                      print a.get('href')
                  

                  【讨论】:

                  • 嗯,当我尝试运行它时,我收到“ImportError: No module named html”,除了 python-lxml 之外我还需要什么吗?
                  • 啊,我有 1.3.6 版本,2.0 及更高版本附带
                  • 确实如此。如果您愿意,我可以提供一个使用 lxml.etree 来完成这项工作的示例吗? lxml.html 更能容忍损坏的 HTML。
                  【解决方案21】:

                  语言:Objective-C
                  图书馆:libxml2 + Matt Gallagher's libxml2 wrappers + Ben Copsey's ASIHTTPRequest

                  ASIHTTPRequest *request = [ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://stackoverflow.com/questions/773340"];
                  [request start];
                  NSError *error = [request error];
                  if (!error) {
                      NSData *response = [request responseData];
                      NSLog(@"Data: %@", [[self query:@"//a[@href]" withResponse:response] description]);
                      [request release];
                  }
                  else 
                      @throw [NSException exceptionWithName:@"kMyHTTPRequestFailed" reason:@"Request failed!" userInfo:nil];
                  
                  ...
                  
                  - (id) query:(NSString *)xpathQuery WithResponse:(NSData *)resp {
                      NSArray *nodes = PerformHTMLXPathQuery(resp, xpathQuery);
                      if (nodes != nil)
                          return nodes;
                      return nil;
                  }
                  

                  【讨论】:

                    【解决方案22】:

                    语言:Perl
                    图书馆:HTML::TreeBuilder

                    use strict;
                    use HTML::TreeBuilder;
                    use LWP::Simple;
                    
                    my $content = get 'http://www.stackoverflow.com';
                    my $document = HTML::TreeBuilder->new->parse($content)->eof;
                    
                    for my $a ($document->find('a')) {
                        print $a->attr('href'), "\n" if $a->attr('href');
                    }
                    

                    【讨论】:

                    • 也是错误的,必须调用$document->eof;如果你使用 $document->parse($html);并在未设置 href 时打印空行。
                    • 恢复到我原来的代码; ->eof() 在此示例中无用;在此示例中,检查 href 是否存在也毫无意义
                    • 您是否有不想使用 new_from_content 的原因?
                    【解决方案23】:

                    语言:PHP 库:DOM

                    <?php
                    $doc = new DOMDocument();
                    $doc->strictErrorChecking = false;
                    $doc->loadHTMLFile('http://stackoverflow.com/questions/773340');
                    $xpath = new DOMXpath($doc);
                    
                    $links = $xpath->query('//a[@href]');
                    for ($i = 0; $i < $links->length; $i++)
                        echo $links->item($i)->getAttribute('href'), "\n";
                    

                    有时将@ 符号放在$doc-&gt;loadHTMLFile 之前很有用,可以抑制无效的html 解析警告

                    【讨论】:

                    【解决方案24】:

                    语言:Python
                    图书馆:HTQL

                    import htql; 
                    
                    page="<a href=a.html>1</a><a href=b.html>2</a><a href=c.html>3</a>";
                    query="<a>:href,tx";
                    
                    for url, text in htql.HTQL(page, query): 
                        print url, text;
                    

                    简单直观。

                    【讨论】:

                      【解决方案25】:

                      语言:Ruby
                      图书馆:Nokogiri

                      #!/usr/bin/env ruby
                      
                      require "nokogiri"
                      require "open-uri"
                      
                      doc = Nokogiri::HTML(open('http://www.example.com'))
                      hrefs = doc.search('a').map{ |n| n['href'] }
                      
                      puts hrefs
                      

                      哪些输出:

                      /
                      /domains/
                      /numbers/
                      /protocols/
                      /about/
                      /go/rfc2606
                      /about/
                      /about/presentations/
                      /about/performance/
                      /reports/
                      /domains/
                      /domains/root/
                      /domains/int/
                      /domains/arpa/
                      /domains/idn-tables/
                      /protocols/
                      /numbers/
                      /abuse/
                      http://www.icann.org/
                      mailto:iana@iana.org?subject=General%20website%20feedback
                      

                      这是对上面的一个小改动,产生可用于报告的输出。我只返回 href 列表中的第一个和最后一个元素:

                      #!/usr/bin/env ruby
                      
                      require "nokogiri"
                      require "open-uri"
                      
                      doc = Nokogiri::HTML(open('http://nokogiri.org'))
                      hrefs = doc.search('a[href]').map{ |n| n['href'] }
                      
                      puts hrefs
                        .each_with_index                     # add an array index
                        .minmax{ |a,b| a.last <=> b.last }   # find the first and last element
                        .map{ |h,i| '%3d %s' % [1 + i, h ] } # format the output
                      
                        1 http://github.com/tenderlove/nokogiri
                      100 http://yokolet.blogspot.com
                      

                      【讨论】:

                        【解决方案26】:

                        语言:Java
                        图书馆:jsoup

                        import java.io.IOException;
                        
                        import org.jsoup.Jsoup;
                        import org.jsoup.nodes.Document;
                        import org.jsoup.nodes.Element;
                        import org.jsoup.select.Elements;
                        import org.xml.sax.SAXException;
                        
                        public class HtmlTest {
                            public static void main(final String[] args) throws SAXException, ValidityException, ParsingException, IOException {
                                final Document document = Jsoup.parse("<html><body><ul><li><a href=\"http://google.com\">google</li><li><a HREF=\"http://reddit.org\" target=\"_blank\">reddit</a></li><li><a name=\"nothing\">nothing</a><li></ul></body></html>");
                                final Elements links = document.select("a[href]");
                                for (final Element element : links) {
                                    System.out.println(element.attr("href"));
                                }
                            }
                        }
                        

                        【讨论】:

                          【解决方案27】:

                          使用 phantomjs,将此文件另存为 extract-links.js:

                          var page = new WebPage(),
                              url = 'http://www.udacity.com';
                          
                          page.open(url, function (status) {
                              if (status !== 'success') {
                                  console.log('Unable to access network');
                              } else {
                                  var results = page.evaluate(function() {
                                      var list = document.querySelectorAll('a'), links = [], i;
                                      for (i = 0; i < list.length; i++) {
                                          links.push(list[i].href);
                                      }
                                      return links;
                                  });
                                  console.log(results.join('\n'));
                              }
                              phantom.exit();
                          });
                          

                          运行:

                          $ ../path/to/bin/phantomjs extract-links.js
                          

                          【讨论】:

                            【解决方案28】:

                            语言:Coldfusion 9.0.1+

                            图书馆:jSoup

                            <cfscript>
                            function parseURL(required string url){
                            var res = [];
                            var javaLoader = createObject("javaloader.JavaLoader").init([expandPath("./jsoup-1.7.3.jar")]);
                            var jSoupClass = javaLoader.create("org.jsoup.Jsoup");
                            //var dom = jSoupClass.parse(html); // if you already have some html to parse.
                            var dom = jSoupClass.connect( arguments.url ).get();
                            var links = dom.select("a");
                            for(var a=1;a LT arrayLen(links);a++){
                                var s={};s.href= links[a].attr('href'); s.text= links[a].text(); 
                                if(s.href contains "http://" || s.href contains "https://") arrayAppend(res,s); 
                            }
                            return res; 
                            }   
                            
                            //writeoutput(writedump(parseURL(url)));
                            </cfscript>
                            <cfdump var="#parseURL("http://stackoverflow.com/questions/773340/can-you-provide-examples-of-parsing-html")#">
                            

                            返回一个结构数组,每个结构包含一个 HREF 和 TEXT 对象。

                            【讨论】:

                              【解决方案29】:

                              语言:JavaScript/Node.js

                              库:RequestCheerio

                              var request = require('request');
                              var cheerio = require('cheerio');
                              
                              var url = "https://news.ycombinator.com/";
                              request(url, function (error, response, html) {
                                  if (!error && response.statusCode == 200) {
                                      var $ = cheerio.load(html);
                                      var anchorTags = $('a');
                              
                                      anchorTags.each(function(i,element){
                                          console.log(element["attribs"]["href"]);
                                      });
                                  }
                              });
                              

                              请求库下载 html 文档,而 Cheerio 允许您使用 jquery css 选择器来定位 html 文档。

                              【讨论】:

                                猜你喜欢
                                相关资源
                                最近更新 更多
                                热门标签