BeautifulSoupでスクレイピングのまとめ

何度かBeautifulSoupについては書いているのですが、未だに使い方が覚えられずにイライラします。仕方が無いのでまとめて置く事にしました。BeautifulSoupはHTMLから情報を取得するだけ無く、HTMLの編集もできますが、ここではスクレイピング用途のみに絞っています。

使用するのは以下のHTMLです。



  

  
one two three
  • one
  • two
  • three

このHTMLを使って色々と情報を取得したのが以下です。覚えるべきはfindAllだけです。注意する必要があるのは、textを指定した場合にタグオブジェクトが取れずに、テキストオブジェクトが取れるので、一旦parentで親のタグ取りましょうという事と、正規表現で条件指定する場合は、re.compileで正規表現オブジェクトを渡すという事位ですか。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import re
import urllib
from BeautifulSoup import BeautifulSoup

html = '''
上記HTML。ここに書くと表示が乱れるので分けました。
'''

def main():
  soup = BeautifulSoup(html)

  # 基本はfindかfindAllでタグ名指定で要素を取得
  links = soup.findAll('a')         
  for link in links:
    print link.name                 # タグ名
    print link.string               # タグの中のテキスト
    print dict(link.attrs)['href']  # attrsはタプルのリストなので辞書経由でアクセスが便利

  blogdiv = soup.find('div', attrs={'id':'blog'})  # タグ名に加えてattrsで属性条件を入れる
  bloglinks = blogdiv.findAll('a')                 # 要素に対してもfind/findAll可能。子要素からの検索になる
  for link in bloglinks:
    print link  # 要素をそのまま出力すると、その部分のHTMLになる

  # タグ内のテキストで検索
  firstlinks = soup.findAll(text="one")            
  for link in firstlinks:
    print link.parent  # テキストで検索した場合はテキストオブジェクトが取れる。タグにアクセスしたい場合はparent経由

  # findAllのタグ条件はリストで複数指定可能
  li_or_a = soup.findAll(['a', 'li'])              
  for tag in li_or_a:
    print tag

  # テキスト検索も複数指定可能
  one_or_two = soup.findAll(text=['one', 'two'])   
  for tag in one_or_two:
    print tag

  # recursiveを無効にすれば、自身の子要素からのみ検索できる
  only_children = soup.find('body').findAll('div', recursive=False)
  for div in only_children:
    print div

  # 各属性の条件指定には正規表現オブジェクトを指定できる
  dot_com_links = soup.findAll('a', attrs={'href':re.compile(r'.*?\.com')})
  for link in dot_com_links:
    print dict(link.attrs)['href']

  # タグ名とテキスト内容を同時に指定しても、タグは取れない
  firstlinks = soup.findAll('a', text="one")
  for link in firstlinks:
    print link.parent  # やっぱりparentを経由する必要がある


if __name__ == '__main__': main()

書いてみると何故こんな事が覚えられないのか謎ですが、とにかくこれでBeautifulSoupは使えるようになりましたね。あと以前にも書きましたが、現状のBeautifulSoupだと解析できないHTMLが存在します。その場合は僕はこうしてますが、もっと上手い方法あったら教えて下さい。

一応これでスクレイピングは出来る気がしますが、Web::Scraperと違い、必要な情報を構造化して取得する事ができないのが面倒ですね。ラッパー書きたいなぁと思いながら中々重い腰が上げられません。

Leave a Reply

Your email address will not be published. Required fields are marked *