欅坂**のブログ画像を並列処理で取得する。

はじめに

僕は学生最後の年末を一日中実装をしていた。実家の厳しい環境下でも関係なくただ、ひたすらに"パソコンカタカタオタク"を演じた。一段落し年末の特番をなんの目的もなく漠然と観ていたら「pythonという言語はシングルスレットで動いておりマルチスレッドには対応していないから「並列化」しなくては」という言葉が降ってきたこれはもしかしたら天命かもしれない。

並列化とは

並列化(へいれつか)は、コンピュータにおいて、同時に複数の演算処理を実行すること(並列計算)によって処理のスループットを上げるプログラミング手法である。 並列化の主な内容は全体の問題をいくつかの独立したタスクに分割し、タスクをプロセッサに割り当て、それらのタスクを同調させて最終結果を得ることである。並列化は本質的に並列化可能な(主にデータに依存性のない)問題にのみ適用できる。問題の分割手法には領域分割、機能分割があり、両方を組み合わせることもある。(Wikipediaより)

pythonではthreading (すれっでぃんぐ)というモジュールでスレッドベースの並列処理を行う。

実装

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from bs4 import BeautifulSoup
import sys
from urllib import request
import os.path
import os
import re 
import threading
 
# url先の画像を保存する関数
def download(url):
    url = "http://www.keyakizaka46.com"+ url
    headers = {
              "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0",
                      }
    print(url)
    req = request.Request(url, None, headers)
    img = request.urlopen(req)
    localfile = open(os.path.basename(url), 'wb')
    localfile.write(img.read())
    img.close()
    localfile.close()

def download_instance(url,page,n):
    for i in range(n):
        p_s = str(int(page) + i)
        par_url = url + "&id=" + p_s
        print(par_url)
        res = request.urlopen(par_url) # beautifulsoupでパース
        soup = BeautifulSoup(res.read(),"html.parser")
        pattern = r"/files/14/diary/k46/member/moblog/"
# ページに存在するimgタグを検索
        for link in soup.find_all('img'):
# 画像URLを取得
            img_url = link.get('src')
            match_img = re.search(pattern,img_url)
            if match_img:
                #print ("http://www.keyakizaka46.com"+img_url)
# ローカルに画像をダウンロード
                download(img_url)
            else:
                pass

#http://www.keyakizaka46.com/mob/news/diarKijiShw.php?site=k46o&ima=0000&id=(101から始まる記事番号)&cd=member

def main():
    par_url = "http://www.keyakizaka46.com/mob/news/diarKijiShw.php?site=k46o&ima=0000&id="
    page = 101 + int(input("start page:"))
    n = int(input("get page:"))
    t1 = threading.Thread(target=download_instance, name="download_instance", args=(par_url,page,n))
    t1.start()
    t1.join()
    print("end")
if __name__ == '__main__':
    main()

取得できた

f:id:syu-m-5151:20161231232916p:plain やった~!!!

最後に

並列化についてはもっと、真剣に勉強しないと成果が出なさそう…。あとボクのPCは"こあつーでぃお”だった…。 では、皆様よいお年を~~~

 参考

17.1. threading — スレッドベースの並列処理 — Python 3.5.3 ドキュメント

アイドルのホームページから画像を自動で取得するオタク気持ち悪い() - じゃあ、おうちで学べる

Pythonのマルチスレッドプログラミング - Python入門