はじめに
2024 年、皆様いかがお過ごしでしょうか。
最近めっぽう寒くなりマフラーが手放せない季節になってきたなという印象ですが、そう感じるのは昨年の 12 月は例年より暖かかったからかなとも思ってます。
そんな 2023 年 12 月は、年末ということもありアドベントカレンダーの季節でした。
私は会社でアドベントカレンダーの運営を行っており、今年の成果について社内で共有することがありました。
そこで、皆さんの書いてくれた記事はどの程度いいねをもらっているのか?どんなタグの記事が多いのか?を CSV に出力してみたくなったので、今回はそこで作成したスクレイピングのコードを紹介します。
今回のソースコードは以下に公開しています。
実行環境
今回の実装で使用した環境は以下となります。
環境 | バージョン |
---|---|
OS | Windows 10 Pro |
Python | 3.10.4 |
開発
モジュールのインポートする
まずはスクレイピングやデータの CSV 化に必要なモジュールをインポートします。
pip install requests beautifulsoup4 pandas
実際にスクレイピングする
まず、スクレイピングするにあたり「どの年の」「どのカレンダーの」情報を抽出するか決める必要があります。
そのような情報を全てメイン処理の中に記述しても問題はありませんが、設定値として持たせた方が今後も使いやすいと感じたため、別ファイルに記述します。
# 年
year="XXXX"
# カレンダー名
calendar_name="YYYY"
それでは実際のスクレイピングしたコードを以下に示します。処理の流れは以下の通りとなります。
- 設定値で記載した情報から、該当する Advent Calendar のページにアクセスする
- 取得したアドベントカレンダーに投稿している担当者と記事の URL を取得する
- 記事一つ一つの以下の情報を取得する(一人が複数記事投稿している場合があるため、URL をキーとして取得する)
- タイトル
- タグ
- いいね数
- ストック数
- 取得した情報を Pandas DataFrame に変換し、CSV に出力する
import config
import re
import requests
from bs4 import BeautifulSoup
import pandas as pd
def extract_info(url):
"""
qiita記事のURLをスクレイピングし、いいね数やストック数等の情報を抽出する。
"""
if re.search('https\://qiita\.com',url):
res = requests.get(url)
soup = BeautifulSoup(res.content, 'html.parser')
title = soup.find('h1',{'class':'style-wo2a1i'}).text
tags = [x.text for x in soup.find_all('a',{'class':'style-1a4ckru'})]
num_likes = soup.find('div',{'class':'style-2pgeei'}).text
num_stocks = soup.find('div',{'class':'style-krcte5'}).text
return title, tags, num_likes, num_stocks
else:
print(f'URLを確認してください: {url}')
return 0
# 1. Advent Calendarのカレンダーページにアクセス
url = f"https://qiita.com/advent-calendar/{config.year}/{config.calendar_name}"
res = requests.get(url)
soup = BeautifulSoup(res.content, 'html.parser')
print("info: Advent calendarのページを取得しました。 URL: " + url + "]")
# 2. 担当者と記事のURLを抽出する
content = soup.find("div", {"class": 'style-1covvrn'})
series = content.find_all("tbody", {"class": 'style-azrjx0'})
authors=[]
urls=[]
for calendar in series:
authors += [x.text.rstrip() for x in calendar.find_all("a", {"class":'style-zzg0i9'})]
urls += [x.find('a').get('href') for x in calendar.find_all("div", {"class":'style-1dctyxx'})]
print("info: 全ての投稿者と記事URLを取得しました。[記事数: " + str(len(authors)) + "]")
# 3. 個別の記事の情報を取得(複数記事記載している場合があるため、キーは記事のURL)
qiita_info_dic = {}
for author, url in zip(authors, urls):
title, tags, num_likes, num_stocks = extract_info(url)
qiita_info_dic[url] = [
author,
title,
tags,
num_likes,
num_stocks
]
print("info: 全ての記事の情報を取得しました。[記事数: " + str(len(authors)) + "]")
# 4. pandas DataFrameにし、CSV化する
output_file_name=f'output/{config.calendar_name}_{config.year}_data.csv'
df = pd.DataFrame.from_dict(qiita_info_dic, orient='index').sort_values(0,ascending=False).reset_index()
df.columns = ['URL','投稿者','タイトル','タグ','いいね数','ストック数']
df.to_csv(output_file_name, index=False, encoding='utf-8')
print("info: 結果をCSVに出力しました。[ファイル名: " + output_file_name + "]")
実行結果
上記スクリプトを実行すると、以下のような標準出力が表示され、output/YYYY_XXXX_data.csv
に結果が出力されます。
今回は私が運営していた NRI OpenStandia Advent Calendar 2023 の情報を取得します。
$ py main.py
info: Advent Calendarのページを取得しました。 URL: https://qiita.com/advent-calendar/2023/nri-openstandia]
info: 全ての投稿者と記事URLを取得しました。[記事数: 50]
info: 全ての記事の情報を取得しました。[記事数: 50]
info: 結果をCSVに出力しました。[ファイル名: output/nri-openstandia_2023_data.csv]
出力された結果は以下のように Excel で表示ができますので、いいね数で並び変えたり、タグ別に集計したり、グラフで表示したりと自由に行えます。
おわりに
いかがでしたでしょうか。今回は Qiita Advent Calendar の記事別いいね数やストック数等の情報をまとめてスクレイピングする方法をご紹介しました。スクレイピングは様々な言語で実装ができると思いますが、その中でも Python は初心者でも非常に使いやすいと感じました。
この記事が少しでも皆さんのお役に立ったなら嬉しいです。最後まで読んでいただきありがとうございました。