TIL

Today I Learned. 知ったこと、学んだことを書いていく

RoboBrowserを使ってWebページにログインしてクローリング

最近、下の本を読んでいる。RoboBrowserと言うものがあるらしいので、使ってみたときのメモ

なんか、フォームに入力したりするときには Requests で行うのは面倒らしいので、 RoboBrowser を使用するっぽい。

GitHub - jmcarp/robobrowser

インストール

pip install robobrowser

RoboBrowserは内部でBeautifulSoupを使用しているため、BeautifulSoup4とRequestsは一緒にインストールされる

nanacoのサイトにログインし、残高確認をしてみる

RoboBrowserを使ったプログラムの作成で、nanacoのサイトにログインして、残高を表示するプログラムを作ってみた

ソースはGitHubにあげた

github.com

フォームの送信

フォームを送信するには、まず、フォームを取得する。フォームを取得するにはRoboBrowser.get_form()を使う。引数にformのidを渡すことでフォームを取得できる。

ログインのフォームを取得する

>>> from robobrowser import RoboBrowser
>>> browser = RoboBrowser()
>>> browser.open('https://www.nanaco-net.jp/pc/emServlet')
>>> form = browser.get_form(id='login_card')
>>> form
<RoboForm _PageID=SCBS_PCB1001, _DataStoreID=DSBS_PCB1001_Control, _SeqNo=1509980487174_[ACTIVE]_ExecuteThread:__19__for_queue:__weblogic.kernel.Default_(self-tuning)___, _ControlID=BS_PCB1001_Control, _WID=NoWID, _ORGWID=, _WIDManager=, _preProcess=, _TimeOutControl=, _WIDMode=0, _WindowName=, _ReturnPageInfo=, XCID=, SECURITY_CD=, ACT_ACBS_do_LOGIN2=>

テキストボックスに入力する

テキストボックスの name を指定し、value属性に値を代入する

>>> form['XCID'].value = '1234567891234567'
>>> form['SECURITY_CD'].value = '1234567'

フォームの送信

送信するときにはRoboBrowser.submit_form()を使う。引数に値を入力したフォームを渡す。送信後の状態が browser に入っているため、selectなどで要素を取得できる。

>>> brawser.submit_form(form)
>>> browser.select('#cardzan > span.time')
[<span class="time">201711052359分時点</span>]

あとはごちゃごちゃ取っていく(適当)


書いている最中になんかエラーが出た

エラー内容

/Users/tamago324/.local/share/virtualenvs/robobrowser-zDYVPytv/lib/python3.6/site-packages/bs4/__init__.py:181: UserWarning: No parser was explicitly specified, so I'm using the best available HTML parser for this system ("html.parser"). This usually isn't a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently.

The code that caused this warning is on line 60 of the file nanaco_zan.py. To get rid of this warning, change code that looks like this:

 BeautifulSoup(YOUR_MARKUP})

to this:

 BeautifulSoup(YOUR_MARKUP, "html.parser")

  markup_type=markup_type))
Traceback (most recent call last):
  File "nanaco_zan.py", line 60, in <module>
    main()
  File "nanaco_zan.py", line 13, in main
    loginedForm = login(browser)
  File "nanaco_zan.py", line 40, in login
    browser['XCID'].value = NANACO_NUM
TypeError: 'RoboBrowser' object is not subscriptable

解決策

インスタンス生成時にparserを指定すればいいらしい

>>> browser = RoboBrowser(parser='html.parser')

python - Robobrowser BeautifulSoup error - Stack Overflow

direnvでディレクトリ内だけの環境変数を設定する

ディレクトリ内での環境変数を設定できる。

Pythonでしか使わない場合にはPipenvを入れたほうが良いかも?

Pipenvについては以下の記事に書いてある

tmg0525.hatenadiary.jp

direnvのインストール

$ brew install direnv

direnvを使えるように設定する。.bashrcに以下の記述を追加する。(使っているエディタがVimの場合)

export EDITOR=vim
eval "$(direnv hook bash)"

使い方

環境変数を設定したいディレクトリに.envrcを作成する。このファイルに記述した環境変数が対象のディレクトリ内でのみ有効になる。

.envrc

export NAME='tamago'

上記の.envrcがあるディレクトリで以下のコマンドを実行すると環境変数が設定されていることがわかる。

$ echo $NAME
tamago

参考文献

pyenv+Minicondaからdirenvに乗り換える - くじらにっき++

改めて、direnvを使いましょう! - HDE BLOG

DataGridViewの行ヘッダーの横幅を変更する - VB.NET

' 行ヘッダーの横幅は表示されているテキストが見えるような横幅
Me._dgv.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders

参考文献

メモし忘れた

DataGridViewで最後の列を横いっぱいに表示する - VB.NET

Dim lastColIndex As Integer = DataGridView1.Columns.Count - 1
Dim lastCol = DataGridView1.Columns(lastColIndex)
lastCol.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill

参考文献

c# - How the Rightmost column of a DataGridView could fill the remaining part of the form? - Stack Overflow

DataGridViewの全ての列幅が表示領域よりも小さかったら最後の列幅を最大まで広げる - VB.NET

頑張って書いたやつのメモ

''' <summary>
''' 全ての列幅が表示領域よりも小さかったら最後の列幅を最大まで広げる
''' </summary>
Public Sub AutoFillLastColumn()
    ' カラムの横幅の合計値
    Dim colWidthSum As Integer = 0

    For Each col As DataGridViewColumn In Me._dgv.Columns
        colWidthSum += col.Width
    Next

    ' 行ヘッダーの横幅も加算する
    colWidthSum += Me._dgv.RowHeadersWidth

    ' 表示領域よりも小さいとき、最後の列を横いっぱいに広げる
    If colWidthSum < Me._dgv.ClientSize.Width Then
        ' 最後の列
        Dim lastCol As DataGridViewColumn = Me._dgv.Columns(Me._dgv.Columns.Count - 1)
        lastCol.AutoSizeMode = DataGridViewAutoSizeColumnsMode.Fill
    End If
End Sub

これ作るのに結構時間かかった。

参考文献

メモし忘れた