Python3メモ - BeautifulSoup4のあれこれ

BeautifulSoupとは

Beautiful Soup is a Python library for pulling data out of HTML and XML files. It works with your favorite parser to provide idiomatic ways of navigating, searching, and modifying the parse tree. It commonly saves programmers hours or days of work.

Beautiful Soup Documentation — Beautiful Soup 4.4.0 documentation より引用

 

 BeautifulSoupのインストールとインポート

pip3 install beautifulsoup4

from bs4 install BeautifulSoup

BeautifulSoupに用いるParserのインストー

pip3 install html.parser

pip3 install lxml

 

BeautifulSoupの簡単な例(アンカータグの抽出)

>>> from bs4 import BeautifulSoup as BS
>>> import requests
>>> page = requests.get("https://www.crummy.com/software/BeautifulSoup/bs4/doc")
>>> soup = BS(page.text, "lxml")

>>> soup.a 
<a accesskey="I" href="genindex.html" title="General Index">index</a>

>>> for anchor in soup.find_all("a"):
...     print("{}({})".format(anchor.string, anchor.get("href")))
...
index(genindex.html)
Beautiful Soup 4.4.0 documentation(#)
¶(#beautiful-soup-documentation)
Beautiful Soup(http://www.crummy.com/software/BeautifulSoup/)
Beautiful Soup 3(http://www.crummy.com/software/BeautifulSoup/bs3/documentation.html)
...

各種の要素の取得・操作等

子要素・親要素・兄弟要素 関連

soup.body.name # bodyのタグ名を返却

 

soup.body.contents #  bodyの子要素をリスト形式で返却

soup.body.children # bodyの子要素をジェネレータ形式で返却

 

soup.body.descendants # bodyの子要素をジェネレータ形式で再帰的に返却

soup.body.strings # bodyの子要素に含まれる文字列全てをジェネレータ形式で返却

 

soup.title.parent # titleの親要素全体を取得

soup.title.parents # titleの親要素を再帰的に取得(BeautifulSoupオブジェクトに行きつくと終了)

 

soup.p.next_sibling # 最初のp要素の次の兄弟要素を取得

soup.p.previous_sibling # 最初のp要素の前の兄弟要素を取得

 

soup.p.next_element # 最初のp要素の次の兄弟要素を取得(要素内も順次取得)

soup.p.previous_sibling最初のp要素の前の兄弟要素を取得(要素内も順次取得)

 検索(find, find_all, select)

soup.find("a") # 最初のa要素を検索

soup.find_all("a") # a要素をリスト形式ですべて取得
# soup("a") ... find_allは省略可能

soup.find_all("a",limit=5) # a要素をリスト形式で5個まで取得

soup.find_all(["a","p"]) # p要素とa要素をリスト形式ですべて取得

soup.find_all(text="piyo") # 要素内に指定文字列を持つ要素を取得

 

def my_filter(t):
    return t.has_attr("id")

soup.find_all(my_filter) # 自作フィルターの利用

 

soup.find_all(id="hoge") # キーワード引数を用いた検索

soup.find_all(attrs={"id":"hoge", "class":"huga"}) # 辞書を用いた複数条件の検索

soup.p.find_all_next() # 最初のp要素以降の要素をすべて取得(再帰的)

soup.p.find_all_previous() # 最初のp要素以前の要素をすべて取得(再帰的)

 

soup.select("#hoge") # idにhogeを持つ要素をCSSセレクタ記法で取得

soup.select(".huga") # classにhugaを持つ要素をCSSセレクタ記法で取得

要素の変更・追加

soup.p.name = "h1" # 最初のp要素をh1要素に変更

soup.p.string = "piyo" # 最初のp要素内をpiyoに変更

soup.p.append("huga") # 最初のp要素内にhugaを追加

soup.p["id"] = "hoge" # 最初のp要素のidをhogeに変更

del soup.p["class"] # 最初のp要素のclass属性を削除

 

soup.body.append(soup.new_tag("p")) # body要素の最後尾にp要素を追加

soup.p.insert_after(soup.new_string("hoge")) # 最初のp要素の直後にhoge文字列を追加

 

soup.p.clear() # 最初のp要素内のコンテンツを削除

soup.p.extract() # 最初のp要素を抽出し返却(抽出されたp要素は削除される)

soup.body.decompose() # body内の要素を全削除

 

soup.p.wrap(soup.new_tag("div")) # 最初のp要素をdiv要素で包む

soup.p.unwrap() # 最初のp要素のタグを外す(返却値はタグ)

 

Python3メモ - Web関連

requestsモジュールを用いたWebコンテンツへのアクセス

>>> import requests

>>> req = requests.open("https://www.google.com")

>>> for k,v in req.headers.items():

...        print("[{}]{}".format(k,v))

[Date]Mon, 10 Jul 2017 04:10:28 GMT

[Expires]-1

[Cache-Control]private, max-age=0

...

>>> print(req.text)
b'<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="ja"><head><meta content="\x90\xa2\x8aE...

 

Web Server

PythonのWebフレームワークを用いることで,リクエストとレスポンスといった基本的な処理から,URLルーティング・動的ページ生成・セッション管理といった複雑な処理まで行うことができる.

Bottle

from bottle import run, route, static_file

 

@route("/")
def root():
return static_file("index.html", root=".")

 

@route("/<yourname>")
def yourname(yourname):
return "Hello! {}".format(yourname)

 

run(host="localhost", port=9999)

 Flask

from flask import Flask, render_template, request

app = Flask(__name__)

 

@app.route("/")
def main():
    return app.send_static_file("index.html")

 

@app.route("/echo/<arg1>/<arg2>")
def echo(arg1, arg2):
    k = {}
    k["path1"] = arg1
    k["path2"] = arg2
    k["get1"] = request.args.get("get1")
    k["get2"] = request.args.get("get2")
    return render_template("template.html", **k)

app.run(port=9999, debug=True)

template/template.html

<html>
<head><title>Flask</title></head>
<body>
<p>path1: {{path1}}</p>
<p>path2: {{path2}}</p>
<br>
<p>GET1: {{get1}}</p>
<p>GET2: {{get2}}</p>
</body>
</html>

 

Webスクレイピング

BeautifulSoup

def get_links(url):
    import requests
    from bs4 import BeautifulSoup as soup

    html = soup(requests.get(url).text)
    links = [element.get("href") for element in html.find_all("a")]
    return links


url = input("URL : ")
for i, link in enumerate(get_links(url), start=1):
    print(i,link)

 

参考文献 : 入門Python3 O'REILLY

Python3メモ - 文字列関連

 Python3の忘れそうな文字列関連のメソッド等々についてのメモ

  • string.find(word)
    string内において,最初にwordが出現する位置を返す
    >>> alphabet = "abcdefghijklmnopqrstuvwxyz"
    >>> alphabet.find("k")
    10

  • string.replace(str1, str2, time)
    string内のstr1をstr2へ最大time回置換する
    >>> greeting = "Good Morning, Good Evening, Good Night"
    >>> greeting.replace("Good", "Bad", 2)
    'Bad Morning, Bad Evening, Good Night'


  • string内の一部を変更する
    stringはimmutableなオブジェクトなので,直接変更はできない

    >>> text = "Hello morld"
    >>> text[6] = "w"
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: 'str' object does not support item assignment

  • 解決法1 : listに一旦変換して変更する
    >>> text = "Hello morld"
    >>> text_list = list(text)
    >>> text_list[6] = "w"
    >>> text = "".join(text_list)
    >>> text
    'Hello world'
  • 解決法2 : スライスを用いる

    >>> text = "Hello morld"
    >>> text = text[:6] + "w" + text[7:]
    >>> text
    'Hello world'