【问题标题】:How can I get href links from HTML using Python?如何使用 Python 从 HTML 获取 href 链接?
【发布时间】:2011-03-05 18:28:33
【问题描述】:
import urllib2

website = "WEBSITE"
openwebsite = urllib2.urlopen(website)
html = getwebsite.read()

print html

到目前为止一切顺利。

但我只想要纯文本 HTML 中的 href 链接。我怎么解决这个问题?

【问题讨论】:

    标签: python html hyperlink beautifulsoup href


    【解决方案1】:

    试试Beautifulsoup:

    from BeautifulSoup import BeautifulSoup
    import urllib2
    import re
    
    html_page = urllib2.urlopen("http://www.yourwebsite.com")
    soup = BeautifulSoup(html_page)
    for link in soup.findAll('a'):
        print link.get('href')
    

    如果您只想要以http:// 开头的链接,您应该使用:

    soup.findAll('a', attrs={'href': re.compile("^http://")})
    

    在带有 BS4 的 Python 3 中,它应该是:

    from bs4 import BeautifulSoup
    import urllib.request
    
    html_page = urllib.request.urlopen("http://www.yourwebsite.com")
    soup = BeautifulSoup(html_page, "html.parser")
    for link in soup.findAll('a'):
        print(link.get('href'))
    

    【讨论】:

    • BeautifulSoup 不能自动关闭meta 标签,例如。 DOM 模型无效,无法保证您一定会找到所需的内容。
    • bsoup 的另一个问题是,链接的格式会改变原来的格式。因此,如果您想更改原始链接以指向另一个资源,目前我仍然不知道您是如何使用 bsoup 做到这一点的。有什么建议吗?
    • 并非所有链接都包含http。例如,如果您对网站进行编码以删除协议,则链接将以 // 开头。这意味着只需使用网站加载的任何协议(http:https:)。
    • 提醒大家最近看到这个答案,BeautifulSoup3在Python 3中不再支持,最新版本是BeautifulSoup4,可以通过from bs4 import BeautifulSoup导入
    【解决方案2】:

    您可以使用HTMLParser 模块。

    代码可能看起来像这样:

    from HTMLParser import HTMLParser
    
    class MyHTMLParser(HTMLParser):
    
        def handle_starttag(self, tag, attrs):
            # Only parse the 'anchor' tag.
            if tag == "a":
               # Check the list of defined attributes.
               for name, value in attrs:
                   # If href is defined, print it.
                   if name == "href":
                       print name, "=", value
    
    
    parser = MyHTMLParser()
    parser.feed(your_html_string)
    

    注意:HTMLParser 模块在 Python 3.0 中已重命名为 html.parser。将源转换为 3.0 时,2to3 工具会自动调整导入。

    【讨论】:

    • 我意识到,如果一个链接包含特殊的 HTML 字符,例如 &,它会被转换成它的文本表示,例如 & 在这种情况下。如何保留原始字符串?
    • 我最喜欢这个解决方案,因为它不需要外部依赖
    • @swdev - 我意识到这已经晚了几年,但是 url 编码/解码是如何处理的。
    【解决方案3】:

    看看使用漂亮的soup html解析库。

    http://www.crummy.com/software/BeautifulSoup/

    你会做这样的事情:

    import BeautifulSoup
    soup = BeautifulSoup.BeautifulSoup(html)
    for link in soup.findAll("a"):
        print link.get("href")
    

    【讨论】:

    • 谢谢!但是使用link 而不是a
    【解决方案4】:

    将 BS4 用于此特定任务似乎有点过头了。

    试试吧:

    website = urllib2.urlopen('http://10.123.123.5/foo_images/Repo/')
    html = website.read()
    files = re.findall('href="(.*tgz|.*tar.gz)"', html)
    print sorted(x for x in (files))
    

    我在http://www.pythonforbeginners.com/code/regular-expression-re-findall 上找到了这段漂亮的代码,并且非常适合我。

    我仅在从 web 文件夹中提取文件列表的场景中对其进行了测试,该文件夹公开了其中的 files\folder,例如:

    我得到了 URL 下文件\文件夹的排序列表

    【讨论】:

      【解决方案5】:

      与真正的大师相比,我的答案可能很糟糕,但是使用一些简单的数学、字符串切片、find 和 urllib,这个小脚本将创建一个包含链接元素的列表。我测试了谷歌,我的输出似乎是正确的。希望对您有所帮助!

      import urllib
      test = urllib.urlopen("http://www.google.com").read()
      sane = 0
      needlestack = []
      while sane == 0:
        curpos = test.find("href")
        if curpos >= 0:
          testlen = len(test)
          test = test[curpos:testlen]
          curpos = test.find('"')
          testlen = len(test)
          test = test[curpos+1:testlen]
          curpos = test.find('"')
          needle = test[0:curpos]
          if needle.startswith("http" or "www"):
              needlestack.append(needle)
        else:
          sane = 1
      for item in needlestack:
        print item
      

      【讨论】:

        【解决方案6】:

        在 BeautifulSoup 和 Python 3 中使用请求:

        import requests 
        from bs4 import BeautifulSoup
        
        
        page = requests.get('http://www.website.com')
        bs = BeautifulSoup(page.content, features='lxml')
        for link in bs.findAll('a'):
            print(link.get('href'))
        

        【讨论】:

          【解决方案7】:

          这是@stephen 答案的懒惰版本

          import html.parser
          import itertools
          import urllib.request
          
          class LinkParser(html.parser.HTMLParser):
              def reset(self):
                  super().reset()
                  self.links = iter([])
          
              def handle_starttag(self, tag, attrs):
                  if tag == 'a':
                      for (name, value) in attrs:
                          if name == 'href':
                              self.links = itertools.chain(self.links, [value])
          
          
          def gen_links(stream, parser):
              encoding = stream.headers.get_content_charset() or 'UTF-8'
              for line in stream:
                  parser.feed(line.decode(encoding))
                  yield from parser.links
          

          像这样使用它:

          >>> parser = LinkParser()
          >>> stream = urllib.request.urlopen('http://stackoverflow.com/questions/3075550')
          >>> links = gen_links(stream, parser)
          >>> next(links)
          '//stackoverflow.com'
          

          【讨论】:

            【解决方案8】:

            这是迟到的回答,但它适用于最新的 python 用户:

            from bs4 import BeautifulSoup
            import requests 
            
            
            html_page = requests.get('http://www.example.com').text
            
            soup = BeautifulSoup(html_page, "lxml")
            for link in soup.findAll('a'):
                print(link.get('href'))
            

            别忘了安装“requests”和“BeautifulSoup”包以及“lxml”。将 .text 与 get 一起使用,否则会引发异常。

            "lxml" 用于删除要使用哪个解析器的警告。您也可以使用适合您情况的“html.parser”。

            【讨论】:

              【解决方案9】:

              此答案与 requestsBeautifulSoup 的其他答案类似,但使用列表理解。

              因为find_all()是Beautiful Soup搜索API中最流行的方法,你可以使用soup("a")作为soup.findAll("a")的快捷方式并使用列表推导:

              import requests
              from bs4 import BeautifulSoup
              
              URL = "http://www.yourwebsite.com"
              page = requests.get(URL)
              soup = BeautifulSoup(page.content, features='lxml')
              # Find links
              all_links = [link.get("href") for link in soup("a")]
              # Only external links
              ext_links = [link.get("href") for link in soup("a") if "http" in link.get("href")]
              

              https://www.crummy.com/software/BeautifulSoup/bs4/doc/#calling-a-tag-is-like-calling-find-all

              【讨论】:

                【解决方案10】:

                对我来说最简单的方法:

                from urlextract import URLExtract
                from requests import get
                
                url = "sample.com/samplepage/"
                req = requests.get(url)
                text = req.text
                # or if you already have the html source:
                # text = "This is html for ex <a href='http://google.com/'>Google</a> <a href='http://yahoo.com/'>Yahoo</a>"
                text = text.replace(' ', '').replace('=','')
                extractor = URLExtract()
                print(extractor.find_urls(text))
                
                

                输出:

                ['http://google.com/', 'http://yahoo.com/']

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多