Slide 1

Slide 1 text

による Webスクレイピング入門 uc

Slide 2

Slide 2 text

今日話すこと スクレイピングとは HTMLとは Pythonとは 前期教養のお知らせをスクレイピングする 実践してみよう

Slide 3

Slide 3 text

スクレイピングとは ウェブサイトの情報をプログラムによって抜き出して 加工すること

Slide 4

Slide 4 text

スクレイピングとAPIによるアクセスの違い スクレイピング データ提供元はプログラムによるアクセスを想定していない HTMLなど表示用のデータしか利用できない →必要なデータを抜き出して加工する必要がある APIによるアクセス データ提供元がプログラムによるアクセスを想定している XMLやJSONなどプログラムに扱いやすい構造のデータを利用できる

Slide 5

Slide 5 text

スクレイピング vs API 可能ならAPIを利用しよう APIを提供しているようなサービスはだいたいスクレイピングを禁止している /robots.txtを見ればプログラムによるアクセスを許可しているかがわかる スクレイピングによるアクセスが頻繁すぎてアクセス先に負荷をかけると BAN・訴訟・逮捕もありえるので注意

Slide 6

Slide 6 text

前期教養のお知らせ http://www.c.u-tokyo.ac.jp/zenki/news/index.html の構造を調べてみよう Windowsの人 F12キー か Ctrl + Shift + I Macの人 ⌘ + option + I

Slide 7

Slide 7 text

HTMLとは HyperText Markup Languageの略 HyperText 文字だけでなくリンクや画像も入れられるすごいテキスト Markup Language 文章構造を記述するための言語 cf. プログラミング言語 リンクや画像を入れたり、文章構造を記述するためにタグが用いられる タグは<タグ名>のように記述される

Slide 9

Slide 9 text

HTML主要タグ
ページの部品を区別するなど 文章の一部を区別するなど 見出し (■ = 1, 2, 3, 4, 5, 6)

パラグラフ リンク 画像

    ,
      箇条書き
    • 箇条書きの項目 表

Slide 10

Slide 10 text

CSSについて かつてはHTMLのタグでフォントや文字の色、文字寄せなどを決めていた 現在はHTMLには文章構造のみを記述し、見た目はCSS (Cascading Style Sheets) で記述することになっている

Slide 11

Slide 11 text

Pythonとは お手軽プログラミング言語 大体のことは短くおしゃれに書ける ライブラリが豊富 最初から付いている標準ライブラリだけでも十分強力 外部ライブラリを使えば機械学習もお手の物 マルチパラダイム いろんなプログラミング言語のおいしいところをつまみ食い

Slide 12

Slide 12 text

Pythonのダメなところ 遅い PyPyとか使えば速くもできるけどお手軽ではなくなる 間違った記述の記事が多い なるべく公式ドキュメントを見るようにしよう

Slide 13

Slide 13 text

Pythonをインストールしよう https://www.python.org/ からPython3をインストール 2019/09/27現在の最新版は3.7.4 ターミナルに $ python -V (以後Macはpythonの代わりにpython3コマンドを使用) と打ってインストールしたバージョンと一致しているか確認 $ python と打つと対話環境が起動する

Slide 14

Slide 14 text

変数・算術演算子 数 >>> x = 1 >>> x + 2.34 3.34 文字列 >>> s = “It’s ” >>> t = ‘showtime!’ >>> s + t It’s showtime!

Slide 15

Slide 15 text

リスト >>> l = [1, 3.14, ‘abc’] >>> l[1] 3.14 >>> l.append([7, 8]) >>> l [1, 3.14, ‘abc’, [7, 8]] >>> len(l) 4

Slide 16

Slide 16 text

辞書 >>> d = {‘name’: ‘hiroshi’, ‘age’: 35} >>> d[‘name’] ‘hiroshi’ >>> d.update(job=’office worker’) >>> d {‘name’: ‘hiroshi’, ‘age’: 35, ‘job’: ‘office worker’}

Slide 17

Slide 17 text

if文 >>> if 1 > 2: ... print(‘1 is greater than 2.’) ... else: ... print(‘1 is not greater than 2.’) ... 1 is not greater than 2.

Slide 18

Slide 18 text

in演算子 bool演算子 >>> if 2 in [1, 2, 3]: ... print(‘2 in [1, 2, 3] == True’) 2 in [1, 2, 3] == True >>> ‘工業’ in ‘東京工業大学’ and ’工業’ not in ‘東京大学’ True

Slide 19

Slide 19 text

for文 >>> members = [‘scott’, ‘Virgil’, ‘Alan’, ‘Gordon’, ‘John’] >>> for member in members: ... print(member) ... Scott Virgil Alan Gordon John

Slide 20

Slide 20 text

こんなforはやめよう >>> for i in range(len(members)): >>> print(members[i]) for文の中でインデックスを使いたいときは? >>> for i, member in enumerate(members): ... print(str(i+1) + ‘: ‘ + member) ... 1: Scott 2: Virgil 3: Alan 4: Gordon 5: John

Slide 21

Slide 21 text

関数 >>> def add1(num): ... return num + 1 ... >>> add1(3) 4

Slide 22

Slide 22 text

クラス >>> class Dog(): ... def __init__(self, name): ... self.name = name ... def bark(self): ... print(‘I am ‘ + self.name) ... >>> dog = Dog(‘sushi’) >>> print(dog.name) sushi >>> dog.bark() I am sushi

Slide 23

Slide 23 text

ライブラリのインポート モジュール ライブラリとして利用できるソースコードが書かれたファイル パッケージ モジュールを集めたフォルダ インポート パッケージやモジュールをプログラムで使えるようにすること

Slide 24

Slide 24 text

ライブラリのインポート import tkinter import tkinter as tk import tkinter.filedialog from tkinter import ttk, filedialog from tkinter.filedialog import (FileDialog as FD, askdirectory as ad, N, NS, NSEW)

Slide 25

Slide 25 text

仮想環境を作成する やらなくても基本的に問題なし $ python -m venv zenkinews $ cd zenkinews $ Scripts\activate (Windows) $ source zenkinews/bin/activate (Mac)

Slide 26

Slide 26 text

BeautifulSoupをインストールしよう Anacondaとか使ってる人はpipを使うと環境が崩壊するよ! $ pip3 install beautifulsoup4 pip Pythonのパッケージマネージャ BeautifulSoup Pythonの外部モジュールの1つ PythonでHTMLを解析するのに役立つ

Slide 27

Slide 27 text

お知らせページをスクレイピングしてみよう プログラムをダウンロード プログラムを実行 $ python3 zenki_news.py ターミナルにお知らせがずらっと出たら成功

Slide 28

Slide 28 text

プログラムのソースコード from urllib.request import urlopen from bs4 import BeautifulSoup url = 'http://www.c.u-tokyo.ac.jp/zenki/news/index.html' html = urlopen(url) soup = BeautifulSoup(html, 'html.parser') div = soup.find('div', id='newslist2') dds = div.find_all('dd') for dd in dds: print(dd.a.text)

Slide 29

Slide 29 text

その気になればimport以外は1行で書ける from urllib.request import urlopen from bs4 import BeautifulSoup print(‘\n’.join(dd.a.text for dd in BeautifulSoup(urlopen('http://www.c.u-tokyo.ac.jp/zenki/news/index.html'), 'html.parser').find('div', id='newslist2').find_all('dd')))

Slide 30

Slide 30 text

プログラムを1文ずつ解説します

Slide 31

Slide 31 text

from urllib.request import urlopen urllibパッケージのrequestモジュールからurlopen関数をインポートする urllibパッケージは標準ライブラリなので最初から入っている

Slide 32

Slide 32 text

from bs4 import BeautifulSoup bs4モジュールからBeautifulSoupクラスをインポートする

Slide 33

Slide 33 text

url = 'http://www.c.u-tokyo.ac.jp/...' url変数にお知らせのURL文字列を代入

Slide 34

Slide 34 text

html = urlopen(url) インポートしたurlopen関数を使って、お知らせページのHTMLを取得する html変数にはお知らせページのHTMLソースが文字列として代入される

Slide 35

Slide 35 text

soup = BeautifulSoup(html, 'html.parser') 取得したHTMLを、BeautifulSoupクラスがhtml.parserモジュールを使って soupインスタンスに変換する html.parser Pythonに最初から入っている標準モジュールの1つ。 HTMLをタグと中身に分けてくれる。(トークン化) パーサーというよりレキサー。 soup HTMLをPythonのオブジェクトに変換したもの。 HTMLをパースしたDOMツリー。

Slide 36

Slide 36 text

阿部寛のホームページのソース 阿部寛のホームページ http://abehiroshi.la.coocan.jp/

Slide 37

Slide 37 text

そのsoupのイメージ soup .head .meta [‘http-equiv’] = ‘Content-Type’ [‘content’] = ‘text/html; charset=x-sjis’ .title .string = ‘阿部寛のホームページ ’ .frameset [‘cols’] = [18, 82] .frame [‘src’] = ‘menu.htm’ [‘marginheight’] = 0 [‘marginwidth’] = 0 [‘scrolling’] = ‘auto’ [‘name’] = ‘left’

Slide 38

Slide 38 text

例 阿部寛のホームページのタイトルを知りたい ↓ soup.head.title.string または soup.find(‘title’).string

Slide 39

Slide 39 text

div = soup.find('div', id='newslist2') soupの中からid属性が “newslist2” の
要素を検索して抜き出す

Slide 40

Slide 40 text

dds = div.find_all('dd') 先ほど抜き出した
要素の中から、
要素をすべて抜き出す

Slide 41

Slide 41 text

ddsの内容 dds[0] .a [‘href’] = ‘http://www.c.u-tokyo.ac.jp/zenki/news/kyoumu/2019SS2_tuishi_nittei.pdf’ [‘target’] = ‘_blank’ .string = ‘2019年度Sセメスター(S2ターム)追試験時間割(再掲)’ .img [‘src’] = ‘http://www.c.u-tokyo.ac.jp/zenki/news/kyoumu/images/common/icon_pdf.gif’ dds[1] .a [‘href’] = ‘http://www.c.u-tokyo.ac.jp/zenki/news/kyoumu/20190924engineering.pdf’ [‘target’] = ‘_blank’ .string = ‘【工学部より】2020年度工学部システム創成学科 進学内定の学生各位’ .img [‘src’] = ‘http://www.c.u-tokyo.ac.jp/zenki/news/kyoumu/images/common/icon_pdf.gif’ dds[2] .a [‘href’] = ‘http://www.c.u-tokyo.ac.jp/zenki/news/kyoumu/firstyear/2019/0920170054.htm .string = 留年・降年による英語二列の履修について

Slide 43

Slide 43 text

soupの実態 soup.bodyのようにしてbody要素にアクセスできるが、soupがbody属性を 持っているわけではない Pythonのオブジェクトの存在しない属性を参照しようとすると、そのクラスの __getattr__メソッドが呼ばれ、その戻り値が属性の値として戻ってくる これを利用して存在しない属性にアクセスできるようにしている タグ属性にはsoup.body[‘id’]でアクセスできるが、これも__getitem__メ ソッドを使っている

Slide 44

Slide 44 text

実践してみよう それぞれのお知らせのリンク先のアドレスを出力してみよう それぞれのお知らせの左にある日付を出力してみよう 日付とお知らせをセットで出力してみよう 1年生向けのお知らせだけ出力してみよう 結果をファイルに保存してみよう 適当な新聞のトップニュースを出力してみよう

Slide 45

Slide 45 text

それぞれのお知らせのリンク先のアドレス print(dd.a.text) ↓ print(dd.a[‘href’])

Slide 46

Slide 46 text

お知らせの左にある日付 dds = div.find_all(‘dd’) ↓ dts = div.find_all(‘dt’) または dts = div(‘dt’)

Slide 47

Slide 47 text

日付とお知らせをセットで出力 for dt, dd in zip(div(‘dt’), div(‘dd’)): print(dt.text + ‘, ‘ + dd.a.text) zip 複数のリストをまとめてforで参照できる関数

Slide 48

Slide 48 text

1年生向けのお知らせだけ出力 for dt, dd in zip(div(‘dt’), div(‘dd’)): if ‘firstyear’ in dt(‘img’)[1][‘src’]: print(dd.a.text)

Slide 49

Slide 49 text

結果をファイルに保存 from pathlib import Path ︙ ︙ dds = div.find_all(‘dd’) with Path(‘result.txt’).open(‘w’) as f: for dd in dds: f.write(dd.a.text + ‘\n’) pathlib ファイルパスをスマートに扱える標準モジュール

Slide 50

Slide 50 text

次のステップ 定期的にアクセスして監視したい mapleにプログラムを設置してcronで定期実行 得られたデータをSNSに投稿したい RequestsライブラリでOAuth認証・APIを叩く

Slide 51

Slide 51 text

おわり 仮想環境を使った人はお片付けしましょう $ deactivate