【Python】スクレイピング ~ Beautiful Soup 4 ~

■ はじめに

スクレイピング (scraping)を扱っている動画があって
簡単そうだったので、メモ。

■ Beautiful Soup 4

スクレイピングについては、Beautiful Soup 4を使う。

インストール

conda install beautifulsoup4

■ サンプル

例1:Hello world
例2:J1順位
例3:Google画像検索から画像ファイルを保存

例1:Hello world

from bs4 import BeautifulSoup

html = """
<html>
<head>
<meta charset="utf-8">
<title>This is a title</title>
</head>
<body>
<a href="/hello.html">Hello world</a>
<h1>Programming</h1>
<ul>
  <li>Python</li>
  <li>C#</li>
  <li>Java</li>
</ul>
</body>
</html>
"""

soup = BeautifulSoup(html, "lxml")

print("Title : {}".format(soup.title.string))

print("A : {}".format(soup.find('a').string))

for li in soup.select("li"):
  print("Li : {}".format(li.getText()))

出力結果

Title : This is a title
A : Hello world
Li : Python
Li : C#
Li : Java

例2:J1順位

from bs4 import BeautifulSoup
from urllib import request

with request.urlopen('https://www.jleague.jp/standings/j1/') as response:
  content = response.read()

charset = response.headers.get_content_charset()
html = content.decode(charset, 'ignore')
soup = BeautifulSoup(html, "lxml")

table = soup.find_all('tr')

standing = []
for row in table:
  tmp = []
  for item in row.find_all('td'):
    if item.a:
      tmp.append(item.text[0:len(item.text) // 2])
    else:
      tmp.append(item.text)
  del tmp[0]
  del tmp[-1]
  standing.append(tmp)

for item in standing:
  print(item)

出力結果例

['順位', 'クラブ名', '勝点', '試合数', '勝', '分', '負', '得点', '失点', '得失点']
['1', 'サンフレッチェ広島', '3', '1', '1', '0', '0', '3', '0', '3']
['2', '柏レイソル', '3', '1', '1', '0', '0', '4', '2', '2']        
['3', 'FC東京', '3', '1', '1', '0', '0', '3', '1', '2']
['4', '浦和レッズ', '3', '1', '1', '0', '0', '3', '2', '1']        
['5', 'ガンバ大阪', '3', '1', '1', '0', '0', '2', '1', '1']
['6', 'セレッソ大阪', '3', '1', '1', '0', '0', '1', '0', '1']
['7', 'ベガルタ仙台', '1', '1', '0', '1', '0', '1', '1', '0']
['7', '横浜FC', '1', '1', '0', '1', '0', '1', '1', '0']
['7', '名古屋グランパス', '1', '1', '0', '1', '0', '1', '1', '0']
['7', 'ヴィッセル神戸', '1', '1', '0', '1', '0', '1', '1', '0']
['11', '川崎フロンターレ', '1', '1', '0', '1', '0', '0', '0', '0']
['11', 'サガン鳥栖', '1', '1', '0', '1', '0', '0', '0', '0']
['13', '湘南ベルマーレ', '0', '1', '0', '0', '1', '2', '3', '-1']
['14', '横浜F・マリノス', '0', '1', '0', '0', '1', '1', '2', '-1']
['15', '大分トリニータ', '0', '1', '0', '0', '1', '0', '1', '-1']
['16', '北海道コンサドーレ札幌', '0', '1', '0', '0', '1', '2', '4', '-2']
['17', '清水エスパルス', '0', '1', '0', '0', '1', '1', '3', '-2']
['18', '鹿島アントラーズ', '0', '1', '0', '0', '1', '0', '3', '-3']

例3:Google画像検索から画像ファイルを保存

from bs4 import BeautifulSoup
import requests
import urllib.request

def gather_images(key_word, max_image=1000):
  url = "https://www.google.co.jp/search?tbm=isch&q={key_word}&gws_rd=ssl".format(
    key_word=key_word)

  soup = BeautifulSoup(requests.get(url).text)
  images = soup.find_all('img', limit=max_image)
  counter = 1
  for image in images:
    image_url = image.get('src')
    if not image_url or not 'https' in image_url:
      continue
    raw_image = urllib.request.urlopen(image_url).read()
    image_file = "C:\\tmp\\{}_{}.jpg".format(key_word, counter)
    print("image_file = {}".format(image_file))
    with open(image_file, 'wb') as file:
      file.write(raw_image)
    counter = counter + 1

def main():
  gather_images("蝋燭")

if __name__ == '__main__':
  main()

参考文献

https://gammasoft.jp/blog/difference-find-and-select-in-beautiful-soup-of-python/
https://www.atmarkit.co.jp/ait/articles/1910/18/news015.html
https://www.atmarkit.co.jp/ait/articles/1910/18/news015_2.html

関連記事

Python ~ 基本編 / ファイル読込・書込 ~
https://dk521123.hatenablog.com/entry/2019/10/07/000000
Android / Kotlin で画像検索を実装する
https://dk521123.hatenablog.com/entry/2020/09/21/224542