ウェブスクレイピングのためのPython入門

目標

  • AtCoderのABCにおけるA,B問題がスラスラ解け、C問題の標準的な解答レベルのコードを理解できる。
  • Pythonを含めてプログラミングの全体像を知る。
  • ウェブスクレイピングのコードを調べながら実装できる。

内容

  1. 環境構築
  2. 四則演算、変数、文字列、標準入出力、組み込み関数、文字列操作
  3. 型、データ構造
  4. 論理演算子、比較演算子、if文
  5. for文、while文
  6. 関数、ライブラリ
  7. ファイル入出力、まとめ
  8. Pythonの復習、htmlの基礎
  9. ウェブスクレイピング①
  10. ウェブスクレイピング②

参考になるサイト

環境構築

プログラミング全般

Python

ウェブ開発

スクレイピング

環境構築

Pythonの環境構築を行う。また、プログラムがどのようなものかについても説明する。

1.プログラミングの仕組み

アプリやOSはプログラムでできている。プログラムとはCPUに対する計算や処理の手順のことである。プログラムは膨大な数の命令から出来ており、CPUはそれらの命令を1秒間に数億回もの速度で実行している。

しかし、CPUが直接理解できる言語は決められており、日本語や英語ではなく「機械語」という。機械語は2進法の命令で出来ているが、人間がそれを読むのは難しい。

そのため、人間が読むことができるプログラミング言語で書かれた命令を機械語に自動翻訳させている。この自動翻訳することを「コンパイル」という。 コンパイルしてくれるアプリのことを「コンパイラ」といい、翻訳前のプログラムのことを「ソースコード」という。プログラミング言語によって長所や短所が異なり、処理内容に応じて使い分けされている。

プログラミング言語の例
言語説明
アセンブリ言語機械語の命令を最低限人間が読める程度に書き換えた言語
C言語アセンブリ言語に近い側面も持ち、様々な言語に影響を与えた
C++C言語にオブジェクト指向を取り込むなどして、C言語を拡張した言語
JavaScriptWebサイト制作で使われる言語
Python書きやすく、読みやすいコードを目指して作られた言語

2.Pythonとは何か

今回扱うPythonは1991年にオランダ人のグイド・ヴァン・ロッサム氏によって開発された。
Pythonの良さとして、少ないコードでシンプルに記述できることが挙げられる。Pythonは便利なライブラリが豊富であり、機械学習やWebアプリケーションなど様々な場面で使われる。

しかし、Pythonは、プログラムの命令を1つずつ機械語に翻訳しながら実行するインタプリタ型言語である。それは翻訳を介しながら会話をするようなものであり、処理速度が遅いが、ソースコードをすぐに実行できる利点もある。インタプリタ型言語にはPythonの他にRubyやJavaScriptなどがある。

対して、C言語やJavaなどは、コンパイル型言語はソースコードをいったんすべて機械語に翻訳してから実行するコンパイル型言語である。それはすでにすでに翻訳された外国語の本を読むようなものであり、実行速度が速いが、デバックがしにくい欠点もある。

3.Visual Studio CodeとPythonのインストール

Pythonの実行環境としてこのサイトではVisual Studio Codeを用いる。また、WindowsのPCを用いることを想定する。以下の項目を行ってほしい。

  1. Python:Python3をインストールして使うまで(Windows編)を見ながらPythonをインストール
    • ウイルスチェックはやり方がわからなければしなくてもよい
    • 本記事執筆時点ではPython3.10.6の「Download Windows installer (64-bit)」を選択してインストール
    • 「コマンドプロンプトからPythonを実行する」の項目を行った時に、以下をコピペしてEnterを押すことを追加で行ってほしい
    pip3 install beautifulsoup4 requests openpyxl chromedriver-binary selenium
    
    ライブラリのインストールがすぐに始まるので、しばらくそのままにしておく必要がある。エラーが出なければ完了。
  2. Visual Studio CodeでPythonプログラミングを始める(Windows編)を見ながらVisual Studio Codeをインストール
    • 「マウスホイールでフォントの拡大縮小が出来るように設定する」の項目は行わなくてもよい

4.AtCoderの登録

AtCoderは競技プログラミングのサイトである。AtCoderの簡単な問題は新しいプログラミング言語の基本を習得することに適しており、このサイトでも用いる。

  1. AtCoder の Register ページ から新規登録
    • ユーサー名は原則変更できないため注意
    • ユーザー名はハンドルネームでよい
  2. AtCoder 上の問題一覧を見れるサイト、AtCoder Problemsをブックマーク

5.インストールしたライブラリをVisual Studio Codeに登録

Visual Studio Codeでライブラリやモジュールが could not be resolved になる時の対処法に書いてあることを行う。import djangoの代わりにimport beautifulsoup4 を、print(django.__file__)の代わりにprint(beautifulsoup4.__file__)を入力する。

6.(補足)コマンド

普段PCを使う場合は、マウスでボタンをクリックするなどグラフィカルに操作する。しかし、コマンドプロンプトなどを用いてコマンドでPCを操作することも可能である。慣れれば、ディレクトリの作成などコマンドのほうが速く行える操作も多い。ここではコマンドプロンプトの基本的なコマンドの一部を載せておく。

コマンド名コマンド名の由来機能使い方の例
cdchange directoryカレントディレクトリの変更cd ../www/html
mkdirmake directoryディレクトリを新しく作るmkdir dir2
rmdirremove directoryディレクトリの削除rmdir dir2
deldeleteファイルの削除del a.txt
renrenameファイル名の変更ren a.txt b.txt

Python

以下のサイトを用いる。

以下補足

1.四則演算

電卓のように、整数、小数、複素数の四則計算ができる。

1.1.四則演算子

演算子機能実際の使い方
+加算print(1 + 2)
-減算print(2 - 1)
*乗算print(2 * 3)
**累乗print(6 ** 10)
/除算print(2 / 3)
//除算の商 (切り捨て)print(31 // 7)
%除算の余りprint(31 % 7)
print(1 + 2)    # 3
print(2 - 1)    # 1
print(2 * 3)    # 6
print((3 + 4j) * (2 + 3j)) # -6+7j  Pythonでは複素数も可能
print(6 ** 10)  # 60466176
print(6 / 3)    #  2.0 小数であることに注意
print(6 // 3)   # 2
print(31 // 7)  # 4 (31 = 7*4+3)
print(31 % 7)   # 3

1.2.演算子の優先順位

演算子にも優先順位があるが、数学とほぼ同様なので覚える必要は無い。

Tier演算子
1()
2**
3*, /, //, %
4+, -
5<, <=, >, >=, ==, !=
6not
7and
8or

2.文字列

"python" のように、" (ダブルクオーテーション) に囲まれた文字を文字列 (str) という。
ダブルクオーテーションで囲んでも、シングルクオーテーションで囲んでもよいが、ダブルクオテーションのほうがよく見かける。

print("Python")  # Python
# 同じ結果となる
print('Python')  # Pyhon

#数値や式でもクオテーションで囲むと文字列になる
print(2)    # 2
print("2")  # 2 見た目は同じだが文字列と数値は異なる

print(1 + 2)   # 3
print("1 + 2") # 1 + 2

3.変数

数学と同じように、変数を使うことが出来る。変数には数値だけでなく文字列も代入できる。変数名の大文字と小文字は区別される。また、変数名の細かい付け方のルールは人や環境によって違う。例えば、is_usedと書く人もいれば、isUsedと書く人もいる。言語が推奨している書き方を調べたり、共同開発しているならチームの書き方を統一した方がよい。

x_int = 123
print(x)  # 123
x_str = "hello"
print(x)  # hello

左辺の変数に右辺の値を変数に入れることを代入という。数学の=と違い、左辺と右辺は対等ではないので123 = x_intのような書き方はできない。

また、以下のように変数を使うことでプログラムを見やすく、簡潔に書くことが出来る。

# 醜いコード
print(10 + 1)
print((10 + 1) - 2)
print(((10 + 1) - 2)**2)

# 推奨コード
a = 10 + 1
b = a - 2
c = b**2
print(a)
print(b)
print(c)
また次のように変数に代入されている値に計算をして、元の変数に再び代入するような処理もよく行われる。
x = 2
pritnt(x)  # 2
x = x +3
print(x)   # 5

Pythonにおける=は左辺と右辺が等しいという意味ではなく、右辺の値を左辺の変数に代入することを意味する。そのため、3行目ではxに3を足した数が再びxに代入される。このような処理は次のようにも書ける。

x = 2
print(x)  # 2
x += 3
print(x)  # 5

このことは他の演算子にも成り立つ。

変数 += 式        # 変数 = 変数 + 式
変数 -= 式        # 変数 = 変数 - 式
変数 *= 式        # 変数 = 変数 * 式
変数 /= 式        # 変数 = 変数 / 式
変数 //= 式       # 変数 = 変数 // 式
変数 %= 式        # 変数 = 変数 % 式
変数 **= 式       # 変数 = 変数 ** 式

4.AC してみよう

コピペ AC してみましょう。

a= int(input())
b, c = map(int,input().split())
s = input()
print(a+b+c, s)

4.1. F 文字列 (F-Strings)

f"{変数}" と書くと、変数の値が代入された状態の文字列になる。

print("2 * 3:", 2 * 3)  # 2 * 3: 6
print(f"2 * 3: {2 * 3}")  # 2 * 3: 6
#少し複雑になるが、次の方法も可能
print("2 * 3: {}".format(2 * 3))  # 2 * 3: 6

4.2.出力の書式指定

詳しくは、Python の文字列フォーマット(format メソッドの使い方) を参照。

print("pi = {:.4}".format(3.141592653589793238462643383279))  # 3.142

4.3.エスケープ

シングルクオーテーションを出力する際は、ダブルクォーテーションで囲み、 ダブルクオーテーションを出力する際は、シングルクォーテーションで囲むと、スマートに書ける。

print("シングルクオーテーションは ' です")  # シングルクオーテーションは ' です
print('ダブルクオーテーションは " です')  # ダブルクオーテーションは " です

# もちろん、以下のように出力することも可能
print('シングルクオーテーションは \' です')  # シングルクオーテーションは ' です
print("ダブルクオーテーションは \" です")  # ダブルクオーテーションは " です
print("バックスラッシュは \\ です")  # バックスラッシュは \ です
print("改行は\nです")
# 改行は
# です

4.4.Raw 文字列 (Raw Strings)

制御文字 (\, \n といった特殊な役割を持つ文字のこと。) をそのまま出力。

print("a\\b\nA\\B")
# a\b
# A\B
print(r"a\\b\nA\\B") # a\\b\nA\\B

4.5.sep, end に値を入れる

# default は sep=" "
print(1, 2, 3, sep=" < ")  # 1 < 2 < 3
# default は end="\n" (\n は改行を意味する制御文字)
print("No line break.", end="")  # No line break. (改行なし)#

5.set型:集合

リストと違い、要素に重複が無く、順番も決まっていない。lenaddなどリストと多くの同様の関数が使える。

d = {1, 2, 3, 5, 6, 9}
even = {2, 6}
print(d - even)  # {1, 3, 5, 9}  差集合
print(d | even)  # {0, 1, 2, 3, 4, 5, 6, 8, 9} 和集合
print(d & even)  # {2, 6} 積集合
print(d ^ even)  # {0, 1, 3, 4, 5, 8, 9} 対称差集合

6.tupple型:タプル

Python のタプルとリストの違い、タプルの使いどころ

7.データ構造

データ構造とは、データの集まりをコンピュータプログラムで扱いやすいように、一定の形式で格納したものである。前述のリストや辞書などもデータ構造の1種である。また、よく使われるデータ構造として「スタック」、「キュー」、「優先度付きキュー」、「木構造」などがある。

8.enumerate

リストの要素とともにインデックスも取り出せる。

nums = [3, 1, 4, 1, 5]
for i in range(len(nums)):
    print(f"nums[{i}] = {nums[i]}")
    # nums[0] = 3
    # nums[1] = 1
    # nums[2] = 4
    # nums[3] = 1
    # nums[4] = 5

# 組み込み関数 enumerate を使ってもよい
nums = [3, 1, 4, 1, 5]
for i, num in enumerate(nums):
    print(f"nums[{i}] = {num}")
    # nums[0] = 3
    # nums[1] = 1
    # nums[2] = 4
    # nums[3] = 1
    # nums[4] = 5

9.zip

複数のリストの要素を同時に取り出せる。ループ回数は最も要素数の少ないリストに依存する。

names = ['Alice', 'Bob', 'Charlie']
ages = [24, 50, 18]

for name, age in zip(names, ages):
    print(name, age)
# Alice 24
# Bob 50
# Charlie 18

10.lambda(ラムダ)関数

def calc_rect_area(height, width):
    return height * width

print(calc_rect_area(20, 30))  # 600

# calc_rect_area と等価な関数
calc_rect_area3 = lambda h, w: h * w
print(calc_rect_area3(20, 30))  # 600

11.再帰関数

def pow2(n):
  ans = 1
  for i in range(n):
    ans *= 2
    return ans

def fact(n):
  ans = 1
  for i in range(1, n+1):
    ans *= i
    return ans

ABC234 A

13.その他のPythonの機能(一部)

13.1.エラーと例外

ファイルを開く、ネットからデータを取ってくるなどの処理は必ずしも成功するとは限らない。パーミッション拒否されたり、サーバーと繋がらなかったり、そのようなときにバグを防げる。

13.2.数値計算ライブラリ

データ解析などで使う

13.3.正規表現

プログラミングを学んだなら、AtCoder Beginners Selectionが難なく解ける程度の実装力は身につけておきたいですね。

ウェブスクレイピング

以下のサイトを用いる。
HTML,CSS

スクレイピング全般

BeautifulSoup

XPathについて

Selenium

実際のコード


# https://myafu-python.com/webmarketing/google-result/
# https://yuki.world/python-selenium-quickest-setup/
# https://programmer-life.work/python/selenium-find_element_by_class_name-deprecated

# スクレイピングに必要なライブラリをインポート
import openpyxl
from time import sleep
import chromedriver_binary
from selenium import webdriver
from selenium.webdriver.common.by import By

# from bs4 import BeautifulSoup
# import requests
# import csv

# オプション定義
options = webdriver.ChromeOptions()
options.add_experimental_option("excludeSwitches", ["enable-logging"])
options.use_chromium = True

# googleで検索する文字
search_string = "防災井戸 inurl:https://www.pref.osaka.lg.jp/"

# Seleniumを使うための設定とgoogleの画面の表示
INTERVAL = 2.5
URL = "https://www.google.com/"
driver = webdriver.Chrome(options=options)
sleep(INTERVAL)
driver.get(URL)
sleep(INTERVAL)

# 文字を入力して検索
driver.find_element(By.NAME, "q").send_keys(search_string)
driver.find_elements(By.NAME, "btnK")[1].click()
sleep(INTERVAL)

# 検索結果の一覧を取得する
results = []
while True:
    g_ary = driver.find_elements(By.CLASS_NAME, "g")
    for g in g_ary:
        result = {}
        result["url"] = g.find_element(By.CSS_SELECTOR, ".yuRUbf a").get_attribute("href")
        result["title"] = g.find_element(By.TAG_NAME, "h3").text
        results.append(result)

    if len(g_ary) == 10:
        driver.find_element(By.ID, "pnnext").click()
        sleep(INTERVAL)
    else:
        break

# エクセルファイルに書き込み
excel = r"c:\記事収集\google.xlsx"
wb = openpyxl.load_workbook(excel)

sheet = wb["input"]
sheet["a1"] = "タイトル"
sheet["b1"] = "URL"

for row, result in enumerate(results, 2):
    sheet[f"a{row}"] = result["title"]
    sheet[f"b{row}"] = result["url"]

wb.save(excel)
driver.close()

print("finish")