Python
初心者

Pythonによるスクレイピング&機械学習のお勉強その2-1 - ログインの必要なサイトからダウンロード

今回の目標

このシリーズでは教科書(文献1)に沿ってPythonによるスクレイピングと機械学習を学びます。今回は第2章「高度なスクレイピング」から2-1「ログインの必要なサイトからダウンロード」を学びます。

原則、教科書のサンプルプログラムを作成してゆきますが、著作権に配慮し、できるだけそのままではなく類題を作成して勉強してゆく方針です。

方法と結果

  • 準備

その0で作成した学習用docker環境でpythonの実行を行います。
BeautifulSoup4はdocker環境にインストール済です。

$ docker run -t -i -v $HOME/src:$HOME/src pylearn2 /bin/bash

類題2-1

この節ではrequestsモジュールを使ってログインの必要なサイトからHTTP POSTメソッドを使ってセッション通信を行う方法を学びます。アクセスするサイトは著者ご紹介による「作詞掲示板」です。
教科書のサンプルコードはメインプログラムの一本道だったのですが、今回は類題として再利用できそうな部分をクラスと関数を使って書き換えます。

login-getfav-cclef.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pylearn as pl

import requests
from bs4 import BeautifulSoup as bs
from urllib.parse import urljoin

# セッションを管理するクラス
class SessionManager:

    def __init__(self, loginurl, username, password):
        self.loginurl = loginurl
        self.login_info = {
            'username_mmlbbs6': username,
            'password_mmlbbs6': password,
            'back': 'index.php',
            'mml_id': 0
        }
        self.session = None

    #セッションをオープンする 返り値はログインURLページのコンテンツ
    def openSession(self, force=False):
        if (self.session is None) or force:
            self.session = requests.session()
            response = self.session.post(self.loginurl, data=self.login_info)
            response.raise_for_status()
            #print(response.text)
            return response.text

    def getPage(self, url):

        if self.session is None:
            openSession()

        pageurl = urljoin(self.loginurl, url)
        response = self.session.get(pageurl)
        response.raise_for_status()
        return response.text


#ページコンテンツからCSSセレクタで要素を選択する。list=Trueの場合リストで返す
def selectPage(content, selector, list=False):
    soup = bs(content, 'html.parser')
    if list is True:
        return soup.select(selector)
    else:
        return soup.select_one(selector)

#ユーザー名、パスワード、ログインURLのハードコード
USER = '******'
PASS = '******'
url_login = 'https://******/users.php?action=login&m=try'

# ここからメインプログラム

#SessionManagerインスタンスを作成
sm = SessionManager(url_login, USER, PASS)

#セッションをオープン
loginpage = sm.openSession()

#ログインページを解析
a = selectPage(loginpage, '.islogin a', False)

if a is None:
    print('マイページが取得できませんでした')    
    quit()

# 相対URLを絶対URLに変換
url_mypage = urljoin(url_login, a.attrs['href'])
print('マイページ=', url_mypage)

# マイページの情報を取得
mypage = sm.getPage(url_mypage)

# マイページを解析し、お気に入りの詞のタイトルを列挙
links = selectPage(mypage, '#favlist li > a', True)
for a in links:
    href = a.attrs['href']
    title = a.get_text()
    print('-', title, '>', href)

  • 実行結果
$  python ./login-getfav-cclef.py
マイページ= https://******/users.php?user_id=32
- 春に咲く花 by Homary > post.php?mml_id=407
- ジャパニーズインザブラック by Homary > post.php?mml_id=326
- httpsにしないといけない by JS-TESTER > post.php?mml_id=411
- ネジ by JS-TESTER > post.php?mml_id=408
- スクラップブック by JS-TESTER > post.php?mml_id=409
- 聞こえない by JS-TESTER > post.php?mml_id=410
- 今日も明日もJS三昧 by JS-TESTER > post.php?mml_id=161
- 眠ってもデバッグ by JS-TESTER > post.php?mml_id=162
- プリンとシュークリーム by JS-TESTER > post.php?mml_id=246
- 吾輩はテスターである by JS-TESTER > post.php?mml_id=268
- 吾輩はテスターである その2 by JS-TESTER > post.php?mml_id=269
- test by JS-TESTER > post.php?mml_id=281
- test2 by JS-TESTER > post.php?mml_id=288
- 憎しみの果て by JS-TESTER > post.php?mml_id=291
- test1 by JS-TESTER > post.php?mml_id=297
- 無題 by JS-TESTER > post.php?mml_id=318
- 無題 by JS-TESTER > post.php?mml_id=358
- 無題 by JS-TESTER > post.php?mml_id=359
- 吾輩は爆薬である by JS-TESTER > post.php?mml_id=380
- クローリングララバイ by JS-TESTER > post.php?mml_id=402
- ラット・リフ by Homary > post.php?mml_id=401
- メダリオン by Homary > post.php?mml_id=164
- 桜花 by Homary > post.php?mml_id=172
- 格好 by Homary > post.php?mml_id=167
- ぼんやり by Homary > post.php?mml_id=181
- Seraphim by Homary > post.php?mml_id=180
- 命想い by Homary > post.php?mml_id=184
- 夕日 by Homary > post.php?mml_id=202
- 昭和ノスタルジック by Homary > post.php?mml_id=220
- つまびく by Homary > post.php?mml_id=209
- 哀愁メトロ by Homary > post.php?mml_id=207
- Razury by Homary > post.php?mml_id=239
- 鍵 by Homary > post.php?mml_id=247
- キャベツ by Homary > post.php?mml_id=262
- メモリーズ by Homary > post.php?mml_id=256
- memo by Homary > post.php?mml_id=267
- 親愛なる君へ・・・ by Homary > post.php?mml_id=265
- Horror killer by Homary > post.php?mml_id=264
- 黄昏時 by Homary > post.php?mml_id=276
- 人間なんて飽きました by Homary > post.php?mml_id=273
- オカモッチ by Homary > post.php?mml_id=283
- 僕の足 by Homary > post.php?mml_id=302
- チャイルドスカイ by Homary > post.php?mml_id=296
- 学校行こうよ by Homary > post.php?mml_id=306
- オルタナティブ by Homary > post.php?mml_id=305
- 命の価値 by Homary > post.php?mml_id=323
- 病魔 by Homary > post.php?mml_id=317
- Radish Legs by Homary > post.php?mml_id=327
- クリエイト by Homary > post.php?mml_id=350
- そして僕は空を愛した by Homary > post.php?mml_id=342

Discussion

今回のプログラムの肝は、セッション通信のためにrequestsモジュールのsession機能を使うことと、HTTPのGETメソッドだけでなくPOSTメソッドを使うことにあったと考えられます。requestsを使った場合、GETでもPOSTでも辞書型のデータを与えるだけであとの処理は内部でやってくれるので、なかなかよい使い勝手でした。

今回達成したこと

  • requestsライブラリのsession機能を使うことでログインの必要なサイトからのダウンロードの基本を学びました。

参考文献

  1. クジラ飛行机, Pythonによるスクレイピング&機械学習[開発テクニック], ソシム株式会社, 2016