39680


Pythonを勉強したくクローラーを制作しているのですが、下記のコードを賢く短くしたいです。  
HTMLのbody以下のタグを調べながらwebサイトのURLだけをリストに追加していくプログラムです。

[code]

    def _extract_url_links(html):
    """extract url links
    >>> _extract_url_links('aa<a href="link1">link1</a>bb<a href="link2">link2</a>cc')
    ['link1', 'link2']
    """
    #"html.parser"はなるべくpython標準のparserモジュールを使うように指定しているBeautifulSoup()で
    #BeautifulSoupで扱えるようにしている。
    all_url = []
    body_soup = BeautifulSoup(html, "html.parser").find('body')
    #aタグを全て持ってくる。
    for child_tag in body_soup.findChildren():
        if child_tag.get('href') is not None:
            if '#' not in child_tag.get('href'):#or '.png' or '.jpg' or '.gif' 
                if '.jpg' not in child_tag.get('href'):
                    if '.png' not in child_tag.get('href'):
                        if '.gif' not in child_tag.get('href'):
                            all_url.append(child_tag.get('href'))
    return all_url
    
[/code]

これで少しは短くなると思うのですがスッキリしないので他にいい方法はないでしょうか？  
よろしくお願いします。

[code]

    def _extract_url_links(html):
    
        all_url = []
        body_soup = BeautifulSoup(html, "html.parser").find('body')
    
        for child_tag in body_soup.findChildren():
            if child_tag.get('href') is not None:
                if '#' not in child_tag.get('href') or '.jpg' not in child_tag.get('href') or '.png' not in child_tag.get('href') or'.gif' not in child_tag.get('href'):
        return all_url
    
[/code]

詳しい方回答お願いします。

Pythonの正規表現を使う事はわかりました。ただ引数をどのように設定したらいいのかわかりません。#,.png,.jpg,.gifのようにしたいのですがどのように書けば良いのでしょうか？

[code]

    import re
     m = re.search(r'ここの引数をどうしたらいいのかわかりません',child_tag.get('href'))
     if m is not None;
        all_url.append(child_tag.get('href'))
    
[/code]


CC BY-SA 3.0
2017-11-18T08:30:19.803
39678
2017-11-19T14:14:15.220
2017-11-19T14:08:08.393
3054
22565
question
python python3
Pythonでフラグメント（ハッシュ）か画像の拡張子があるURLを除外したい


[`urllib.parse.urlparse`](https://docs.python.jp/3/library/urllib.parse.html)と[`str.endswith`](https://docs.python.jp/3/library/stdtypes.html?highlight=endswith#str.endswith)を使う例です。

  * ハッシュ部の有無の判定:  
元コードの `'#' not in` は、URLにフラグメント（ハッシュ）が無いことを判定したいのだと思いますので、`urlparse` の戻り値の
`fragment` を使い、`not url_parts.fragment` で判定しています。

  * 拡張子のマッチ:  
元コードの `'.gif' not in` などはパス名に画像ファイルの拡張子が付いていないことを判定したいのだと思いますが、そのままだと例えば
`https://www.gift.example.com/` などもはじいてしまいますので、`urlparse` の戻り値の `path`
のみを対象に判定するようにしています。  
正規表現が利用できますが、今回は `endswith` メソッドでも十分そうです。

（念のため注記しますと、URLが画像ファイルの拡張子を含んでいなくとも、そのURLが画像を提供することはあります。あるいは、画像ファイルの拡張子を持ちながら、HTMLなどの別のものを提供するURLもあります。これは実際にアクセスしないと判別できないことです）

* * *
[code]

    #!/usr/bin/python3
    # python2ではurlparseというモジュール名でした
    from urllib.parse import urlparse
    
    # テスト用URL
    urls = (
        "https://example.com",
        "https://example.com/abc.html",
        "https://example.com/abc.html#top",
        "https://example.com/abc.jpg",
        "https://example.com/abc.jpg?v=123",
        "https://www.gift.example.com/",
    )
    
    img_suffixes = (".png", ".jpg", ".gif")
    all_url = []
    for url in urls:
        url_parts = urlparse(url)
        if not url_parts.fragment and not url_parts.path.endswith(img_suffixes):
            all_url.append(url)
    print(all_url)
    
[/code]

出力:

[code]

    ['https://example.com', 'https://example.com/abc.html', 'https://www.gift.example.com/']
    
[/code]


CC BY-SA 3.0
2017-11-18T14:00:33.407
39680
2017-11-19T14:14:15.220
2017-11-19T14:14:15.220
3054
3054
39678
answer