見出し画像

文系大学生がプログラミング(スクレイピング)で作業効率を上げたお話 技術編

この記事は自分用の忘備録として。
でも、どこかの誰かの参考になればとも思いつつ。
*お願い*
本記事のコードやその他の点において、非合理的な点や、お見苦しい箇所があるかもしれません。あるでしょう。ご容赦ください。

ご注意事項

スクレイピングは時として諸刃の剣になり得ます。訪問先Webサーバに過負荷を与えないよう調整しましょう。また、スクレイピングを禁止しているサービスもあります。実際に行う際は、くれぐれも自己責任で。

ことの始まり。

ある日、ゼミの教授から『俺の書庫を整理したいからデータベース作りたい。誰かやってくんね?』ということで、アルバイトを引き受けたのが始まり。当初は、タイトルと筆者を手作業で入力していたものの、600冊以上あるとのことだったのでプログラムを組んだ方が早いと判断した。そこで以下の手順で作業の効率化を図ることにした。

作業フロー

1. iPhoneのアプリ「QRcode_Barcode」で書籍のISBNコードのバーコードを読み込み、csvファイルとしてAirDropでMacに転送。
2. 上のcsvファイルを元に、Pythonを使用してスクレイピングを実行する。
*「QRcode_Barcode」を選んだ理由は、履歴をcsvファイルにできるから。
*今回は『オンライン書店Honya Club』さんのサイトを拝借。

動作環境

MacBook Pro (13-inch, Mid 2012)  Version 10.14.6 (18G87)
Python 3.7.3

コード(Python)と雑な解説

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
import pandas as pd
import csv

1/2行目で「chromedriver」の設定をしたよ。前提として、ここでは自分の「Google Chrome」のバージョンに対応したやつをダウンロードしていること。詳しくは「chromedriver」でググろう。
3行目で「BeautifulSoup」の設定をしたよ。詳しくはググろう。
4/5行目で「csv」関連の設定をしたよ。これもググろう。

df = pd.read_csv('csvファイルの場所/history.csv', encoding='cp932', dtype='object')

li = df.values.tolist()
isbn_list  = [x[2] for x in li] #リストの内包表記

6行目では読み込むcsvの場所を指定しよう。場合によってはエンコードも必要になるかも。うん、ググろう。
7/8行目ではcsvファイル内のISBNコードをisbn_listに格納するよ。

#ブラウザを開く
      driver = webdriver.Chrome('/chromedriverの場所/chromedriver')
      #URLを開く
      driver.get("https://www.honyaclub.com/shop/default.aspx")
      for isbn in isbn_list:
              #isbn入力
              driver.find_element_by_id("id_q").send_keys(isbn)
              #検索ボタンをクリックする
              driver.find_element_by_class_name("search-bt").click()
              #検索結果のページのHTMLをBeautifulSoupに流し込む
              soup = BeautifulSoup(driver.page_source, "lxml")
              #必要部分をCSSセレクタで指定し、テキストを抜き出す
              driver.find_element_by_id("id_q").clear()

              ti = []
              au = []
              result = []

              for i in soup.select("#main > form > div > div.result-item > div > div > dl > dt > a"):
                      ti.append(i.text)
              for b in soup.select(".item-block04 > dl:nth-child(2) > dd:nth-child(2) > p:nth-child(2)"):
                      au.append(b.text)
              result = ti + au

10~30行目ではISBNコードを元に検索した結果をresultに格納しているよ。

au_string = ",".join(au)
              au_string_new = au_string.replace('\u3000',',').replace('\t','').replace('\n','')
              au_list_new = au_string_new.split(",")
              ti_string = ",".join(ti)
              ti_string_new = ti_string.replace('\t','').replace('\n','')
              ti_list_new = ti_string_new.split(",")
result = ti_list_new + au_list_new

31~37行目では結果の文字列を整理しているよ。

with open('/結果のcsvファイルの場所/result.csv', 'a',encoding="utf_8_sig") as f:
                      writer = csv.writer(f, dialect='excel')
                      writer.writerow(result)

38~40行目で37行目の検索結果を新しい結果のcsvに書き込んでいくよ。
ファイルを置く場所はデスクトップとかでOK。
あとは、14~40行目の繰り返しだよ。

if __name__ == "__main__":
  search_books(isbn_list)

43/44行目はPython実行のおまじないだよ。

全体のコード

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
import pandas as pd
import csv

df = pd.read_csv('csvファイルの場所/ファイル名.csv', encoding='cp932', dtype='object')
li = df.values.tolist()
isbn_list  = [x[2] for x in li] #リストの内包表記

def search_books(isbn_list):
      #ブラウザを開く
      driver = webdriver.Chrome('/chromedriverの場所/chromedriver')
      #URLを開く
      driver.get("https://www.honyaclub.com/shop/default.aspx")
      for isbn in isbn_list:
              #isbn入力
              driver.find_element_by_id("id_q").send_keys(isbn)
              #検索ボタンをクリックする
              driver.find_element_by_class_name("search-bt").click()
              #検索結果のページのHTMLをBeautifulSoupに流し込む
              soup = BeautifulSoup(driver.page_source, "lxml")
              #必要部分をCSSセレクタで指定し、テキストを抜き出す
              driver.find_element_by_id("id_q").clear()

              ti = []
              au = []
              result = []

              for i in soup.select("#main > form > div > div.result-item > div > div > dl > dt > a"):
                      ti.append(i.text)
              for b in soup.select(".item-block04 > dl:nth-child(2) > dd:nth-child(2) > p:nth-child(2)"):
                      au.append(b.text)
              result = ti + au
              au_string = ",".join(au)
              au_string_new = au_string.replace('\u3000',',').replace('\t','').replace('\n','')
              au_list_new = au_string_new.split(",")
              ti_string = ",".join(ti)
              ti_string_new = ti_string.replace('\t','').replace('\n','')
              ti_list_new = ti_string_new.split(",")
              result = ti_list_new + au_list_new
              with open('/結果のcsvファイルの場所/result.csv', 'a',encoding="utf_8_sig") as f:
                      writer = csv.writer(f, dialect='excel')
                      writer.writerow(result)
      driver.quit()
      return
if __name__ == "__main__":
  search_books(isbn_list)

実行結果の例

画像1

14冊分を検索した結果、Mac上での動作時間は50秒弱でした。
*専門誌など、検索がヒットしない場合は、そこだけ空白の行になります。

まとめ

1. プログラムは普通に動くっちゃ動く。
2. 手入力に比べて3倍ほど効率が向上した。
3. 但し、バーコードがない、検索にヒットしない場合は結局手入力。
4.「Google Chrome」をヘッドレス化すれば速度UPが期待出来る。
以上。


この記事が気に入ったらサポートをしてみませんか?