星座占いサイトによってランキングが異なり、各星座占いサイトを合計したら、一番よい運勢が占えるのではないか?と考えて、複数星座占いサイトの順位を合計して、(順位の)値が少なくなる順(運勢が良い順)で並べるpythonスクリプトを作ってみました。なお、pythonだけでなくGoogle Apps Script(GAS)でも作成し、自動化して毎日Mastodonにトゥートしていますので、結果だけ知りたい方はフォローしてください。
※GASでは一部星座占いサイトが取得できていないため、pythonで取得している順位と値が異なります。
Pythonを学習したいという方はこちらから。
こちらから毎日の星座占い順位を見ることができます(Mastodon)。
RyoutaH (@ryoutah@mstdn.jp)
402 Posts, 12 Following, 8 Followers · 本業:ITエンジニア 副業:音楽NFTクリエイター 音楽を多めにつぶやきます。
はじめに
前回の記事同様、スクレイピング先のサイトのUI(ざっくりと記載すると画面)が変わると、要素も変わるので、取得できなくなる可能性があることをはじめにお伝えします。こちらの記事は2023年3月22日時点の記事です。今回紹介するコードでもpython + Seleniumを使用しています。
以前の記事はこちら。
早速コード
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import chromedriver_binary
import datetime
import csv
import os
##各星座の漢字:ひらがな変換辞書
zodiac_table = {
"牡羊座":"おひつじ座",
"牡牛座":"おうし座",
"双子座":"ふたご座",
"蟹座":"かに座",
"獅子座":"しし座",
"乙女座":"おとめ座",
"天秤座":"てんびん座",
"蠍座":"さそり座",
"射手座":"いて座",
"山羊座":"やぎ座",
"水瓶座":"みずがめ座",
"魚座":"うお座"
}
##各星座の順位付けポイントをフォーマット
zodiac_rank_total = {
"おひつじ座":0,
"おうし座":0,
"ふたご座":0,
"かに座":0,
"しし座":0,
"おとめ座":0,
"てんびん座":0,
"さそり座":0,
"いて座":0,
"やぎ座":0,
"みずがめ座":0,
"うお座":0
}
##各星座占いサイトのURL
LINE_url = "https://fortune.line.me/contents/horoscope/"
docomo_url = "https://service.smt.docomo.ne.jp/portal/fortune/src/fortune_ranking.html"
asahi_url = "https://www.asahi.com/uranai/12seiza/"
mezamashi_TV_url = "https://www.fujitv.co.jp/meza/uranai/index.html"
fortune_TV_url = "https://uranaitv.jp/rank_fortune"
TV_asahi_url = "https://www.tv-asahi.co.jp/goodmorning/uranai/"
##星座占いの結果出力フォルダ
os.makedirs("./output/", exist_ok=True)
dt_now = datetime.datetime.now()
output_file_date = dt_now.strftime('%Y%m%d_%H%M')
##星座占いの結果出力ファイル
output_file = "./output/horoscope_{}.csv".format(output_file_date)
##星座占いの結果出力CSVファイルの定義
with open(output_file,'w',encoding='utf-8-sig',newline='') as f:
writer = csv.DictWriter(f,["date","Zodiac","Rank","point"])
writer.writeheader()
##星座占いの結果CSV出力オブジェクト
class SaveItem:
def __init__(self,zodiac,rank,point,output_file):
self.date = dt_now.strftime('%Y%m%d')
self.zodiac = zodiac
self.rank = rank
self.point = point
self.output_file = output_file
def csvoutput(self):
contents = {"date":self.date,"Zodiac":self.zodiac,"Rank":self.rank,"point":self.point}
with open(self.output_file,'a', encoding='utf-8-sig',newline='') as f:
fieldnames = ["date","Zodiac","Rank","point"]
writer = csv.DictWriter(f,fieldnames=fieldnames)
writer.writerow(contents)
##スクレイピング開始
options = webdriver.ChromeOptions()
#Web USB Bluetooth等のエラー出力を除外
options.add_argument('--log-level=3')
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
## LINE サイトスクレイピング##
print("Get Line horoscope")
driver.get(LINE_url)
driver.maximize_window()
LINE_elements = driver.find_elements(by=By.CSS_SELECTOR, value=".zodiac-item_card__LgPbF")
for LINE_element in LINE_elements:
LINE_rank = LINE_element.find_element(by=By.TAG_NAME, value="span").text
#print("LINE_rank is ",int(LINE_rank))
LINE_zodiac = LINE_element.find_element(by=By.CSS_SELECTOR, value=".zodiac-item_name__c4Ypu").text
#print("LINE_zodiac is ",LINE_zodiac)
zodiac_rank_total[LINE_zodiac] += int(LINE_rank)
#print(zodiac_rank_total)
## docomo サイトスクレイピング##
print("Get docomo horoscope")
driver.get(docomo_url)
docomo_elements = driver.find_elements(by=By.CSS_SELECTOR, value=".postRank__list > .postRank__item")
for docomo_element in docomo_elements:
docomo_rank = docomo_element.find_element(by=By.CSS_SELECTOR, value=".postRank__infoHeadImg > img").get_attribute('alt')
#print("rank is ",int(docomo_rank.replace("位","")))
docomo_zodiac = docomo_element.find_element(by=By.CSS_SELECTOR, value=".postRank__infoHeadTtl > h3").text
#print("zodiac is ",docomo_zodiac)
zodiac_rank_total[docomo_zodiac] += int(docomo_rank.replace("位",""))
docomo_secnd_elements = driver.find_elements(by=By.CSS_SELECTOR, value=".rankTggl__list > .postRank__item")
for docomo_secnd_element in docomo_secnd_elements:
docomo_secnd_rank = docomo_secnd_element.find_element(by=By.CSS_SELECTOR, value=".postRank__infoHeadImg > img").get_attribute('alt')
#print("rank is ",int(docomo_secnd_rank.replace("位","")))
docomo_secnd_zodiac = docomo_secnd_element.find_element(by=By.CSS_SELECTOR, value=".postRank__infoHeadTtl > h3").get_attribute("textContent")
#print("zodiac is ",docomo_secnd_zodiac)
zodiac_rank_total[docomo_secnd_zodiac] += int(docomo_secnd_rank.replace("位",""))
#print(zodiac_rank_total)
## asahi_url サイトスクレイピング##
print("Get asahi horoscope")
driver.get(asahi_url)
asahi_elements = driver.find_elements(by=By.CSS_SELECTOR, value="ol.UranaiRank > li")
asahi_rank = 1
for asahi_element in asahi_elements:
#print("rank is ",asahi_rank)
asahi_zodiac = asahi_element.find_element(by=By.CSS_SELECTOR, value="img").get_attribute('alt')
#print("zodiac is ",asahi_zodiac)
zodiac_rank_total[asahi_zodiac] += asahi_rank
asahi_rank = asahi_rank + 1
#print(zodiac_rank_total)
## mezamashi_TV_url サイトスクレイピング##
print("Get mezamashi_TV horoscope")
driver.get(mezamashi_TV_url)
mezamashi_TV_elements = driver.find_elements(by=By.CSS_SELECTOR, value="ul.uranaiList > li")
for mezamashi_TV_element in mezamashi_TV_elements:
mezamashi_TV_rank = mezamashi_TV_element.find_element(by=By.CSS_SELECTOR, value="div.rankAndName > p.rank").text
#print("rank is ",int(mezamashi_TV_rank.replace("位","")))
mezamashi_TV_zodiac = mezamashi_TV_element.find_element(by=By.CSS_SELECTOR, value="div.rankAndName > p.name").text
#print("zodiac is ",mezamashi_TV_zodiac)
zodiac_rank_total[mezamashi_TV_zodiac] += int(mezamashi_TV_rank.replace("位",""))
#print(zodiac_rank_total)
## fortune_TV_url サイトスクレイピング##
print("Get fortune_TV horoscope")
driver.get(fortune_TV_url)
fortune_TV_elements = driver.find_elements(by=By.CSS_SELECTOR, value=".nichiun-rank-item-with-stars")
fortune_TV_rank = 1
for fortune_TV_element in fortune_TV_elements:
#print("rank is ",fortune_TV_rank)
fortune_TV_zodiac = fortune_TV_element.find_element(by=By.CSS_SELECTOR, value=".nichiun-rank-item-with-stars-head-title-top > h3").text
#print("zodiac is ",zodiac_table[fortune_TV_zodiac])
zodiac_rank_total[zodiac_table[fortune_TV_zodiac]] += fortune_TV_rank
fortune_TV_rank = fortune_TV_rank + 1
#print(zodiac_rank_total)
## TV_asahi_url サイトスクレイピング##
print("Get TV_asahi horoscope")
driver.get(TV_asahi_url)
TV_asahi_elements = driver.find_elements(by=By.CSS_SELECTOR, value="ul.rank-box > li")
TV_asahi_rank = 1
for TV_asahi_element in TV_asahi_elements:
#print("rank is ",TV_asahi_rank)
TV_asahi_zodiac = TV_asahi_element.find_element(by=By.CSS_SELECTOR, value="span").text
#print("zodiac is ",TV_asahi_zodiac)
zodiac_rank_total[TV_asahi_zodiac] += TV_asahi_rank
TV_asahi_rank = TV_asahi_rank + 1
#print(zodiac_rank_total)
##ポイントの少ない順(ランキングの合計が上位順にソート)
sorted_rank = sorted(zodiac_rank_total.items(), key=lambda x:x[1])
#print(sorted_rank)
order = 1
##順位を付与し結果をCSV出力
for rank_item in sorted_rank:
#print("zodiac is ",rank_item[0])
#print("rank is ",order)
#print("point is ",rank_item[1])
csv_output = SaveItem(rank_item[0],order,rank_item[1],output_file)
csv_output.csvoutput()
order = order + 1
結果
スクリプトを保存したフォルダと同階層に「output」フォルダが作成され、「horoscope_yyyymmdd_HHMM.csv」という名称で結果が出力されます。結果のCSVはこんな感じです。同じポイントでの同一順序までは考慮に入れていませんが、その点はご理解ください。
date | Zodiac | Rank | point |
20230322 | みずがめ座 | 1 | 22 |
20230322 | いて座 | 2 | 24 |
20230322 | しし座 | 3 | 26 |
20230322 | おひつじ座 | 4 | 35 |
20230322 | おとめ座 | 5 | 38 |
20230322 | おうし座 | 6 | 39 |
20230322 | ふたご座 | 7 | 40 |
20230322 | てんびん座 | 8 | 40 |
20230322 | うお座 | 9 | 44 |
20230322 | さそり座 | 10 | 47 |
20230322 | かに座 | 11 | 54 |
20230322 | やぎ座 | 12 | 59 |
プログラミングを学習して業務に活用したい方はこちらからどうぞ
参考になったら幸いです。
コメント