読者です 読者をやめる 読者になる 読者になる

アメブロのブログ記事をスクレイピングで全件取得する方法

www.adventar.org

1日遅れてしまいましたがアドベントカレンダー22日目です。タイトルの通り、ある特定のユーザーのブログ記事全てを取得する方法について書きたいと思います。よろしくお願いします。

目的

  1. 声優のブログ自動生成を行う為、ブログ記事全てを取得する必要がある
  2. 下記の記事で方法は書いてあったが、それだけだと学びがないのでPython3で行う

qiita.com

結果

まず初めに、麻倉もものブログで試しましたが、↓の記事のタイトルにある"/"によって指定したパスがおかしくなりエラーが出る。

ameblo.jp

次に雨宮天で試すも、同じくタイトルに"/"のある記事が存在するためエラーが発生する。

ameblo.jp

最後に夏川椎菜で試したところ、タイトルに"/"を使用した記事がなかったようで、全件取得することができました。

コード

稚拙なコードでありますが、コピペして実行すると夏川椎菜のブログ記事全てを取得することができます。お試しください。

  • Scraping.py
# coding:utf-8
import re

import requests
from bs4 import BeautifulSoup


def get_entry_list(html):
    url_list = [html]
    while True:
        html = requests.get(html).content
        soup = BeautifulSoup(html, "lxml")
        next_page = soup.find("a", {"class", "skinSimpleBtn pagingNext"})
        if isinstance(next_page, type(None)):
            print("finish")
            return url_list
        else:
            url_list.append(next_page["href"])
            html = next_page["href"]


def get_url(entry_list):
    page_list = []
    for html in entry_list:
        html = requests.get(html).content
        soup = BeautifulSoup(html, "lxml")
        text = soup.find_all("a", {"class", "contentTitle"})
        page_list.append(text)
    print("finish")
    return page_list


def cleanhtml(raw_html):
    cleanr = re.compile("<.*?>")
    cleantext = re.sub(cleanr, "", raw_html)
    return cleantext


def scraping(all_entry_list, BASE_DIRE):
    for entry_list in all_entry_list:
        for url in entry_list:
            title = url.string
            with open("{dir}{title}.txt".format(dir=BASE_DIRE, title=title), "w") as file:
                html = requests.get(url["href"]).content
                soup = BeautifulSoup(html, "lxml")
                div_text = soup.find("div", {"class", "articleText"})
                text = cleanhtml(str(div_text)).strip()
                print("Written file: {0}.txt".format(title))
                file.write(text)
    print("finish")


  • createFiles
from Scraping import get_url, get_entry_list, scraping

name_list = {"Asakura_Momo": "asakuramomoblog", "Amamiya_Sora": "amamiyasorablog",
             "Natukawa_Shiina": "natsukawashiinablog"}
blog_id = name_list["Natukawa_Shiina"]
url = "http://ameblo.jp/{0}/entrylist.html".format(blog_id)
BASE_DIRE = "/Users/username/XXXXXXXXXXXXXX/data/{0}/".format("Natukawa_Shiina")
all_entry_list = get_entry_list(url)
page_list = get_url(all_entry_list)
scraping(page_list, BASE_DIRE)

追記(2017/01/12)

結局、re.subを使ってtitleからスラッシュをとる方法で他の二人も全件取得しました。

def cleanslash(blog_title):
    cleanr = re.compile("/")
    cleantext = re.sub(cleanr, "", blog_title)
    return cleantext