web-dev-qa-db-ja.com

Pythonを使用してHTMLからhrefリンクを取得するにはどうすればよいですか?

import urllib2

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

print html

ここまでは順調ですね。

ただし、プレーンテキストHTMLからのhrefリンクのみが必要です。この問題を解決するにはどうすればよいですか?

40
user371012

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://")})
89
systempuntoout

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に名前が変更されました。2to3ツールは、ソースを3.0に変換するときにインポートを自動的に適合させます。

28
Stephen

美しいスープHTML解析ライブラリの使用を見てください。

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

次のようなことを行います。

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

この特定のタスクに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 でこの気の利いたコードを見つけました。

その中のfiles\folderを公開するWebフォルダーからファイルのリストを抽出するシナリオでのみテストしました。

enter image description here

そして、URLの下にファイル\フォルダのソートされたリストを得ました

8
RaamEE

私の答えは、おそらく実際の教祖と比べるとひどいものですが、単純な数学、文字列スライス、検索、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
5
0xhughes

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'))
3
Spas

これは答えるのが遅いですが、最新の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"どちらのケースにも合うものを使用できます。

2
sak

これが@stephenの回答の怠versionなバージョンです

from urllib.request import urlopen
from itertools import chain
from html.parser import HTMLParser

class LinkParser(HTMLParser):
    def reset(self):
        HTMLParser.reset(self)
        self.links = iter([])

    def handle_starttag(self, tag, attrs):
        if tag == 'a':
            for name, value in attrs:
                if name == 'href':
                    self.links = chain(self.links, [value])


def gen_links(f, parser):
    encoding = f.headers.get_content_charset() or 'UTF-8'

    for line in f:
        parser.feed(line.decode(encoding))
        yield from parser.links

次のように使用します。

>>> parser = LinkParser()
>>> f = urlopen('http://stackoverflow.com/questions/3075550')
>>> links = gen_links(f, parser)
>>> next(links)
'//stackoverflow.com'
2
reubano

この回答は、requestsおよびBeautifulSoupを使用する他の回答と似ていますが、リスト内包表記を使用します。

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