親です。

子ども産まれたんで育児とかについて書きます。映画とか心理学とかITとかの趣味についても書きます。

【Python】webスクレイピング勉強した

どもっす。webスクレイピング勉強したのでまとめ。ちな、この記事は俺が自分の理解をまとめてるだけだから、参考にしたいなら下記のページがおススメです。すげえまとまってるから。(アルファツイッタラーばんくしさんのページだよ)
PythonでWebスクレイピングする時の知見をまとめておく - Stimulator

概要

webスクレイピングについて説明しようとすると、webページがどんな風に出来てるかってことから説明しなきゃならない。ざっくり俺の理解で説明すると、まず、コンピュータの世界にはサーバーとホストってのがある。イメージを持ってもらうには、サーバーってのはすごく性能の良いコンピュータで、ホストってのはみなさんの手元にあるやつだと思って貰えばいい。私たちは普段webページを見るとき、手元のコンピュータを使い、yahoo!とかGoogleとかから検索し、ページを開く。んで、このとき私たちは、この世のどこかにあるサーバーに対して「これこれのページが読みたいんですお願いします」と言って見せてもらっているのだ、実は。
こういうお願いのことをhttp通信という。略を開くと、ハイパーテキストトランスファープロトコルだ。つまり「スッゲエテキストを送ったりするやつ」ってこと。
じゃあ、この「スッゲエテキストを送ったりするやつ」通信というお願いでは、何を送りあっているのだろうか? それは「スッゲエテキスト」だ。
この「スッゲエテキスト」ってのは具体的にはHTMLとかのことで、webページはこれらのプログラム言語で書かれた情報を人間向けに表示してくれている。それで私たちは、普段あの見やすかったりかっこよかったり作成者によってはダサダサのページを見ることができている。
んで、webスクレイピングではこのHTMLを直に読み込み、どんな内容が書かれているのか収集する。これは人間がいちいちwebページを目で見て集めてもいいんだが、プログラミングしてやれば、めっちゃ高速に、眠くなることなくできるようになる。だいたいそういう技術だ、webスクレイピングは。

んで実際のやり方

スクレイピングの仕方ですが、僕が勉強したのは大きく分けて2パターンです。BeautifulSoupとselenium
汁の方はHTMLを落としてきてタグの情報などを元にデータを取れます。
レニウムの方は元々ウェブ言語のテスト用に作られたもので、人がウェブ上で触っているみたいなことができます。その代わり重たいです。

BeautifulSoup

BeautifulSoupでのスクレイピングは大まかに
①requests.get(url)でHTML情報を取得する
②BeautifulSoupでHTMLタグをいじれる状態にする
③いじる
って感じ。下記でそれぞれについて参考のコードとともに解説。
①②

response = requests.get(url)
time.sleep(1)
response.encoding = response.apparent_encoding
    
bs = BeautifulSoup(response.text, 'html.parser')

ここはもうほとんど呪文。

time.sleep(1)

は1秒pythonをおやすみさせるコード。

response.encoding = response.apparent_encoding

は日本語でもいじれるようにするエンコードだ。
んで、

bs = BeautifulSoup(response.text, 'html.parser')

でHTMLをいじれる状態に整形する。引数の一つ目はいじりたいHTMLのtext形式、二つ目は整形するときにどの解析器を使用するか。ただこの解析器の指定は、ばんくしさんのところにも書いてあったけど、

try:
    soup = BeautifulSoup(html, "lxml")
except:
    soup = BeautifulSoup(html, "html5lib")

こうするのが良いらしい。

ちな、俺が作ったのは青空文庫から色々引っこ抜くやつ。
一部うまくいってないけど。

#作家名を指定すると表題、テキスト、書誌をCSV化して落とせる。
import requests, webbrowser, time
from bs4 import BeautifulSoup


# 'http://www.aozora.gr.jp/index_pages/person1257.html#sakuhin_list_1'

def url_html(url):
    response = requests.get(url)
    time.sleep(1)
    response.encoding = response.apparent_encoding
    
    bs = BeautifulSoup(response.text, 'html.parser')
    return bs

def author_url_get(author):
    author_list_url = 'http://www.aozora.gr.jp/index_pages/person_all.html'
    author_list_bs = url_html(author_list_url)
    ol = author_list_bs.select('ol')
    for li in ol[0].select('li'):
        a_author = li.select('a')
        
        print(a_author[0].text + author)

        if a_author[0].text == author:
            author_path = a_author[0].get('href')
            front_path = author_list_url.split('/')
            author_fullpath = '/'.join(front_path[0:4]) + '/' + author_path
            return author_fullpath
    print('合致する著者がいませんでした。')
    return None


def booklist(author_url):
    booklist = []
    print(author_url)
    bs = url_html(author_url)
    
    ol = bs.select('ol')
    books = ol[0].select('li')

    #作品urlの前方に結合するurlの取得
    front_url = author_url.split('/')[0:3]
    front_url = '/'.join(front_url)

    #urlの結合
    for book in books:
        a_book = book.select('a')
        a_book_url = a_book[0].get('href')
        book_fullpath = front_url + a_book_url[1:]
        booklist.append(book_fullpath)
    
    return booklist


# 作品urlからzipファイルのurlを取得。
def zip_get(url):
    bs = url_html(url)
    table_download = bs.select('table.download')
    trs = table_download[0].find_all('tr')
    tr_text_file = trs[1].find_all('td')
    
    #作品のzipファイル名
    td_zip = tr_text_file[2].find('a')

    #作品zipのurl
    td_zip_href = td_zip.get('href')
    if td_zip_href[-3:] == 'zip':
        front_url = url.split('/')[0:5]
        front_url = '/'.join(front_url)
        fullpath_zip = front_url + td_zip_href[1:]
        #zipファイルの取得
        webbrowser.open(fullpath_zip)


author = input('作家名を入力してください')
author_url = author_url_get(author)
if author_url != None:
    booklist = booklist(author_url)
    for book in booklist:
        zip_get(book)
        time.sleep(1)

selenium

seleniumは下記のような感じ。

from selenium import webdriver
browser = webdriver.Firefox()
browser.get('http://toyokeizai.net')
link_elem = browser.find_element_by_link_text('ビジネス')
link_elem.click()
browser = webdriver.Firefox()

こんな感じでブラウザを立ち上げて…

browser.get('http://toyokeizai.net')

アクセスしたいサイトのURLを与え…

link_elem = browser.find_element_by_link_text('ビジネス')
link_elem.click()

IDとかリンクテキストとかで指定していじる!!


こんなもんじゃよ。