Python初心者がpythonはじめて1時間の人でもわかるように説明するつもりです。
まずはともあれコード。いろんな記事からコピペしたりして作ってます。
#convering watch-history.html into dataframe using BeautifulSoup
#このコードはYoutube視聴履歴を時間、タイトル、urlをもつデータフレーム:youtube.csvとurlのみのyoutubeurl.csvを出力します
# その情報をもとに、youtubech.csvに視聴したチャンネルのタイトルを出力します
# その情報をもとに、channels.pngに視聴したチャンネルとその回数をグラフとして出力します。
import pandas as pd
from bs4 import BeautifulSoup
import io, sys
#if your pc environment is not encorded by utf-8, you need folloing
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
#download "watch-history.html" file from "https://takeout.google.com/"
# place the html file in the same direction and open
fname = 'watch-history.html'
f = open(fname, 'r', encoding='utf-8')
text = f.read()
#clean the html file by Beautifulsoup
soup = BeautifulSoup(text, 'lxml')
body = soup.find("body")
items = body.find_all( "div", attrs={"class": "outer-cell mdl-cell mdl-cell--12-col mdl-shadow--2dp"} )
#convert it into dataframe
rows = []
for item in items:
divs = item.find("div", attrs={"class": "content-cell mdl-cell mdl-cell--6-col mdl-typography--body-1"})
tmp = [ i for i in divs ]
links = divs.find_all("a")
watchtime = tmp[-1]
for l in links:
url = l.get('href')
if url.find('channel') == -1:
rows.append( [ watchtime, l.text, url ] )
df = pd.DataFrame( rows, columns=['time', 'title', 'url'] )
#export as csv
df.to_csv('youtube.csv')
(df.loc[:,"url"]).to_csv('youtubeurl.csv')
#getting information of channel from url of the youtube video
#this takes some time
from pytube import YouTube
import tqdm
import numpy as np
#open url csv file to get each video's channel name
fname="youtubeurl.csv"
sentenses=[]
toprint=[]
f=open(fname, encoding="utf-8")
def sortcsv():
global sentenses
for line in f:
sentenses.append(line)
sortcsv()
def getauthor():
global toprint
for sentence in tqdm.tqdm(sentenses):
txt = sentence
urllink='"'+txt.split(',')[1]+'"'
np.pi*np.pi
try:
yt = YouTube(urllink)
toprint.append(yt.author)
except:
print("error: this link is not available any more")
getauthor()
#export as csv file
f=open("youtubech.csv","w",encoding="utf-8")
print(toprint, file=f)
#make a graph which channel you see often (top100)
import collections
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(font='Meiryo')
fname="youtube.ch.csv"
f=open(fname,"w",encoding="utf-8")
text=f.read()
c=eval(text)
for i in c:
if i=="unknown":
c.remove(i)
toprint = collections.Counter(c)
fig = plt.subplots(figsize=(30, 60))
left = np.array([i[0] for i in toprint.most_common(100)])
height = np.array([i[1] for i in toprint.most_common(100)])
plt.rcParams["font.size"] = 1
plt.barh(left, height,align="center")
#save as png life
plt.savefig("channels.png", format="png", dpi=1000)
これは、自分がよく見てるチャンネルをぱっと見でわかるようにするコードです。
apiとかOauth認証とかしんどいのでGoogleデータエクスポートっていう自分のグーグルアカウントから保存されてるデータをエクスポートしてくれるサービスを使います。
参考リンク:Googleデータエクスポートのやり方
自分のアカウントでyoutube投稿してる人はたくさんのエクスポートされたファイルが出て、どこのzipに何が入ってるかわかりにくくなります。一つのzipファイルの最大容量の50GB設定でエクスポートするといいと思います。
エクスポートが終わったらダウンロードできるようになるので、takeout-hogehoge.zipとかいうのを開いてください。その中にネストされたファイルがいっぱいありましていろいろ触ってるとwatch-history.htmlがあると思います(以下➀)。
いよいよpythonコードの説明します。私はwindows10でVScodeっていう開発環境を使ってます。python version 3.9.5環境ですが、多分最新でやれば動くんじゃないかと思います。わかってる人はスキップしてもらって一向にかまわないんですが、pythonってインタプリタ言語って呼ばれるプログラミング言語です。これは人間にわかりやすく書かれたコードを機械がわかるコードに変換してコードを実行する方式のことを言います。で、このとき”こんにちは”とかを16バイトのわけわからん文字列に変換(エンコード)やその逆(デコード)するんですが、この方式がいろいろあります。今回は一貫してUTF-8っていうどんな国の言語もしっかり変換できる万能なエンコード方式を使ってもらいます。(多分デフォルトでそうなってると思います)
環境ができた前提で話を進めます。上のコードをコピペしてPythonの作業領域に好きな名前で保存してください。で、同じレイヤーにwatch-history.htmlを置いてください。コードを自分のエディターで開くと多分警告がいっぱいでると思うんですが、これは外部ライブラリが入ってないからです。今回使ってるライブラリは、pandas,BeautifulSoup,io,sys,pytube,tqdm,numpy,collections,matplotlib,seabornの10個で、pip installでインストールしてください。
参考リンク:pipの使い方
多分これでコードが実行できると思いますので完了するまでの時間で以下のコード説明を読んでみてください。
➀をクロームとかのブラウザで開いてみると視聴したたリンクやタイトル、時間とかが表示されると思います。➀をメモ帳とかで開くと、見慣れない文字の羅列が表示されると思います。最初にこれをBeautifulSoupを使ってきれいにします。それをpandasでデータフレーム型にしてcsvファイルに出力してます。一個目の出力はyoutube.csvで視聴した時間、タイトル、urlがエクセルのデータみたいにして保存されてます。二個目の出力はその中のurlだけを出力したやつです。
次に、視聴した動画のurlからそのチャンネルを特定してyoutubech.csvに出力します。これにはpytubeを使います(めっちゃ遅いです)。numpyとtqdmは残り所要時間とかを表示させるために使ってます。
最後に、そのデータをグラフにして可視化してます。良く視聴してるチャンネルtop100を横棒グラフにします。collectionsで人気順に並べ替えて matplotlib.pyplotで挿画します。
また、こんなコードも作ってみました。
#視聴してるけど登録してないチャンネル
import collections
fname="登録チャンネル.csv"
# sentensesは登録してるチャンネル
sentenses=[]
f=open(fname, encoding="utf-8")
def sortcsv():
global sentenses
for line in f:
list=line.split(",")
try:
chname=list[2]
toappend=chname[:-1]
sentenses.append(toappend)
except:
print("error")
sortcsv()
#read youtubech.csv
fname="youtubech.csv.csv"
f.close
f=open(fname, encoding="utf-8")
text=f.read()
#cは視聴したチャンネル
c=eval(text)
countc=collections.Counter(c)
comc=countc.most_common(1000)
dictc=dict(comc)
removed_value = dictc.pop('unknown')
keys = []
for key in dictc:
keys.append(key)
tourokushiterukedomitenai = set(sentenses) - set(keys)
miterukedotourokushitenai=set(keys)-set(sentenses)
str1="\n".join(tourokushiterukedomitenai)
str2="\n".join(miterukedotourokushitenai)
f=open("youtube.ch.watch.analize.csv","w",encoding="utf-8")
print("登録チャンネルだがあまり見てないもの\n"+str1+"\n********************************************\n"+"よく見ているが登録していないもの\n"+str2,file=f)
これは、登録チャンネルとさっきの人気チャンネルを見比べて、「よく見てるけど登録してないチャンネル」と「登録してるけどあんまり見てないチャンネル」を表示します。
さっきエクスポートしたzipファイルの中にある、登録済みチャンネルの情報が入ってるやつをコピペして「登録チャンネル.csv」としてこのコードと同じディレクトリに保存しときます。これで準備完了!
これは割と高速に動作するはず。
簡単にこのコードを解説すると、視聴したチャンネルとよく見てるチャンネル(top500)をそれぞれリスト(っていう形式の格納箱)に入れてsetっていうメソッド(pythonにもともと組み込んである関数)で比較して導出します。そんなに難しいことはしてないので、もしわからんくても、一行ずつググれば「あーそーゆーことね、完全に理解した。」ってなると思います。
ちょっとでも面白かったなと思ってくれたらリアクションください。モチベになります。
じゃぁ、この辺で。