Appelez - moi frère. 2022-01-15 03:56:10 阅读数:214
Bonjour tout le monde,C'est moi..
Récemment, la série Ghost blowing Light《Yunnan Worm Valley》En ligne.,Comme une série de lampes fantômes,Entreprendre la partie supérieure《Grotte de Longling》Contenu,Et c'est l'original du triangle de fer,L'appel direct des internautes est très beau!
Aujourd'hui,On va utiliserPython.Pour accéder aux commentaires de tous les épisodes actuels(Avec Trailer),Et faire des statistiques de données et des analyses de visualisation,Suivez les internautes pour voir la pièce!
Cet article détaillera les rampes et la visualisation du traitement des données,Enseigner et s'amuser!
Retour en arrière - plan 210905
Recevoir Code+Données
Table des matières:
Tous les commentaires de Tencent Video(Après tout, seule.)
Ouvre.《Yunnan Worm Valley》Lire la page,F12
Entrée dansMode développeur,On glisse et on clique"Voir plus de commentaires",L'adresse réelle de la demande de commentaires peut être trouvée.
Nous recherchons plusieurs adresses d'interface de commentaires pour une analyse comparative,Trouver la loi
https://video.coral.qq.com/varticle/7313247714/comment/v2?callback=_varticle7313247714commentv2&orinum=10&oriorder=o&pageflag=1&cursor=6838089132036599025&scorecursor=0&orirepnum=2&reporder=o&reppageflag=1&source=132&_=1630752996851
https://video.coral.qq.com/varticle/7313247714/comment/v2?callback=_varticle7313247714commentv2&orinum=100&oriorder=o&pageflag=1&cursor=6838127093335586287&scorecursor=0&orirepnum=2&reporder=o&reppageflag=1&source=132&_=1630752996850
https://video.coral.qq.com/varticle/7313258351/comment/v2?callback=_varticle7313258351commentv2&orinum=10&oriorder=o&pageflag=1&cursor=6838101562707822837&scorecursor=0&orirepnum=2&reporder=o&reppageflag=1&source=132&_=1630753165406
Enfin,Nous avons constaté que cette adresse peut être simplifiée comme suit
url = f'https://video.coral.qq.com/varticle/{
comment_id}/comment/v2?'
params = {
'orinum': 30,
'cursor': cursor,
'oriorder': 't'
}
Ces quatre paramètres ont la signification suivante::
orinum
Est le nombre de commentaires par demande,Par défaut10- Oui.,J'ai essayé de trouver le plus de support30- Oui.,Donc ici je vais définir la valeur à 30cursor
Est le commentaire initial de chaque demandeid,La loi du changement peut être réglée à0,La demande suivante utilise le dernier commentaire de la liste des commentaires de la demande précédenteidC'est tout.oriorder
Est le tri des commentaires demandés(tDans l'ordre chronologique,Par défaut est l'autre plus chaud)comment_id
,Chaque épisode en a un.id
Utilisé pour recueillir les commentaires correspondants,C'est pourquoi nous devons encore étudier ça.id
Où obtenirIl vient d'être mentionné que nous devons obtenir des commentaires pour chaque épisodeidDonnées,Il se trouve que nous pouvons obtenir des données de page pour chaque épisode demandé.
Ce qui est important ici, c'est que,Nous utilisons directementrequests
Les données demandées pour chaque page d'épisode ne sont pas exactement les mêmes que celles du côté de la page,Mais les données sont disponibles,On peut trouver quelque chose..
Par exemple,,EpisodeIDLa liste est la suivante::
Commentaires sur l'épisodeidEmplacement:
Et voilà.,On va utiliserreExpression régulière pour l'analyse des données pour obtenir.
Grâce à l'analyse des pages Web et à nos besoins de collecte,L'ensemble du processus peut être divisé en:
import requests
import re
import pandas as pd
import os
# Utilisé pour ramper les données de la page d'épisode
def get_html(url):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",
}
r = requests.get(url, headers=headers)
# Correction du désordre
r.encoding = r.apparent_encoding
text = r.text
# Supprimer les données non - Caractères
html = re.sub('\s', '', text)
return html
# Dans les séries télévisées, etc.id,Pour grimper à l'épisodeidEt commentairesid
def get_comment_ids(video_id):
# Adresse du Répertoire
url = f'https://v.qq.com/x/cover/{
video_id}.html'
html = get_html(url)
data_list = eval(re.findall(r'"vip_ids":(\[.*?\])', html)[0])
data_df = pd.DataFrame(data_list)
comment_ids = []
for tid in data_df.V:
# Adresse par épisode
url = f'https://v.qq.com/x/cover/{
video_id}/{
tid}.html'
html = get_html(url)
comment_id = eval(re.findall(r'"comment_id":"(\d+)"', html)[0])
comment_ids.append(comment_id)
data_df['comment_id'] = comment_ids
data_df['Episode'] = range(1,len(comment_ids)+1)
return data_df
# Obtenir tous les commentaires de l'épisode
def get_comment_content(data_df):
for i, comment_id in enumerate(data_df.comment_id):
i = i+1
# Initial cursor
cursor = 0
num = 0
while True:
url = f'https://video.coral.qq.com/varticle/{
comment_id}/comment/v2?'
params = {
'orinum': 30,
'cursor': cursor,
'oriorder': 't'
}
r = requests.get(url, params=params)
data = r.json()
data = data['data']
if len(data['oriCommList'])==0:
break
# Données des commentaires
data_content = pd.DataFrame(data['oriCommList'])
data_content = data_content[['id', 'targetid', 'parent', 'time', 'userid', 'content', 'up']]
# Commentaires
userinfo = pd.DataFrame(data['userList']).T
userinfo = userinfo[['userid', 'nick', 'head', 'gender', 'hwlevel']].reset_index(drop=True)
# Fusionner les commentaires avec les commentaires
data_content = data_content.merge(userinfo, how='left')
data_content.time = pd.to_datetime(data_content.time, unit='s') + pd.Timedelta(days=8/24)
data_content['Episode'] = i
data_content.id = data_content.id.astype('string')
save_csv(data_content)
# Suivant. cursor
cursor = data['last']
num =num + 1
pages = data['oritotal']//30 + 1
print(f'No{
i}Episode{
num}/{
pages}Les commentaires de page ont été recueillis!')
# Enregistrer les données des commentaires localement
def save_csv(df):
file_name = 'Données des commentaires.csv'
if os.path.exists(file_name):
df.to_csv(file_name, mode='a', header=False,
index=None, encoding='utf_8_sig')
else:
df.to_csv(file_name, index=None, encoding='utf_8_sig')
print('Enregistrement des données terminé!')
Les statistiques de données et les méthodes de visualisation de cette fois peuvent se référer aux tweets précédents《》Et《》Attendez.
Échantillonnage5Regarde ça.
df.sample(5)
Voir les informations sur les données
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 35758 entries, 0 to 35757
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 id 35758 non-null int64
1 targetid 35758 non-null int64
2 parent 35758 non-null int64
3 time 35758 non-null object
4 userid 35758 non-null int64
5 content 35735 non-null object
6 up 35758 non-null int64
7 nick 35758 non-null object
8 head 35758 non-null object
9 gender 35758 non-null int64
10 hwlevel 35758 non-null int64
11 Episode 35758 non-null int64
dtypes: int64(8), object(4)
memory usage: 3.3+ MB
Il a fait des commentaires.,On verra si on l'a.
C'est mon frère.userid
Pour1296690233
,On va vérifier,Je l'ai trouvé.VIP
Quelle classe!6NiveauC'est bon.
df.query('userid==1296690233')
head
Le champ est un portrait,Voyons si c'est le portrait du frère aîné.
from skimage import io
# Afficher l'image de la tête
img_url = df.query('userid==1296690233')['head'].iloc[0]
image = io.imread(img_url)
io.imshow(image)
C'est ça.,C'est ça.!!
Référence du dessin《》,Donc nous sommes iciPandasDessiner une vue avec interaction,Introduction de l'environnement:
import pandas as pd
import pandas_bokeh
pandas_bokeh.output_notebook()
pd.set_option('plotting.backend', 'pandas_bokeh')
Et puis...,Statistiques officielles des données et visualisation début de la présentation
from bokeh.transform import linear_cmap
from bokeh.palettes import Spectral
from bokeh.io import curdoc
# curdoc().theme = 'caliber'
episode_comment_num = df.groupby('Episode')['id'].nunique().to_frame('Nombre de commentaires')
y = episode_comment_num['Nombre de commentaires']
mapper = linear_cmap(field_name='Nombre de commentaires', palette=Spectral[11] ,low=min(y) ,high=max(y))
episode_bar = episode_comment_num.plot_bokeh.bar(
ylabel="Nombre de commentaires",
title="Nombre de commentaires sur la diversité",
color=mapper,
alpha=0.8,
legend=False
)
Nous pouvons voir,Le plus grand nombre de commentaires dans l'épisode 1,Jusqu'à1.7(En milliers de dollars des États - Unis)
,La moitié des commentaires;Suivi de la7Nombre de commentaires pour l'ensemble,Surtout cette semaine.7Chiha.!
df['Date'] = pd.to_datetime(df.time).dt.date
date_comment_num = df.groupby('Date')['id'].nunique().to_frame('Nombre de commentaires')
date_comment_num.index = date_comment_num.index.astype('string')
y = date_comment_num['Nombre de commentaires']
mapper = linear_cmap(field_name='Nombre de commentaires', palette=Spectral[11] ,low=min(y) ,high=max(y))
date_bar = date_comment_num.plot_bokeh.bar(
ylabel="Nombre de commentaires",
title="Nombre de commentaires par date",
color=mapper,
alpha=0.8,
legend=False
)
De8Mois30La journée commence,Les membres peuvent le voir le jour de la première diffusion5Set,En tant que membre, j'ai fini de lire.Nous avons découvert que2Plus de commentaires par jour,Parce que chaque semaine1-3Mise à jour, Le nombre total de commentaires est donc plus élevé ces jours - ci.
df['Temps'] = pd.to_datetime(df.time).dt.hour
date_comment_num = pd.pivot_table(df,
values='id',
index=['Temps'],
columns=['Date'],
aggfunc='count'
)
time_line = date_comment_num.plot_bokeh(kind="line",
legend="top_left",
title="Nombre de commentaires"
)
Courbe des commentaires sur le temps de passage,Nous avons découvert que le jour de la première diffusion8Le nombre d'heures de commentaires a atteint le maximum,Après cela, il est plus conforme au comportement de regarder des séries télévisées:À midi、Plus haut la nuit et minuit.
vip_comment_num = df.groupby('hwlevel').agg(Nombre d & apos; utilisateurs=('userid','nunique'),
Nombre de commentaires=('id','nunique')
)
vip_comment_num['Nombre de commentaires par habitant'] = round(vip_comment_num['Nombre de commentaires']/vip_comment_num['Nombre d & apos; utilisateurs'],2)
usernum_pie = vip_comment_num.plot_bokeh.pie(
y="Nombre d & apos; utilisateurs",
colormap=Spectral[9],
title="CommentateurVIPRépartition des grades",
)
Je dois dire,CommentateurLa plupart d'entre euxVIPUtilisateurs,Pas étonnant que la vidéo de Tencent ait fait ce qu'on appelleVIPOui.VIP...
C'est différent.VIPLe nombre de commentaires par utilisateur variera - t - il??
y = vip_comment_num['Nombre de commentaires par habitant']
mapper = linear_cmap(field_name='Nombre de commentaires par habitant', palette=Spectral[11] ,low=min(y) ,high=max(y))
vipmean_bar = vip_comment_num.plot_bokeh.bar(
y = 'Nombre de commentaires par habitant',
ylabel="Nombre de commentaires par habitant",
title="C'est différent.VIPNombre de commentaires par utilisateur",
color=mapper,
alpha=0.8,
legend=False
)
Présente essentiellement unVIP
Plus le grade est élevé Plus la volonté d'évaluer est élevée!Mais pourquoi??
La plupart des internautes qui écrivent des commentaires sont666,Joli vocabulaire.,Comme le frère aîné.Attendre la mise à jourTrois mots,Combien de caractères sont généralement évalués?
import numpy as np
df['Longueur des commentaires'] = df['content'].str.len()
df['Longueur des commentaires'] = df['Longueur des commentaires'].fillna(0).astype('int')
contentlen_hist = df.plot_bokeh.hist(
y='Longueur des commentaires',
ylabel="Nombre de commentaires",
bins=np.linspace(0, 100, 26),
vertical_xlabel=True,
hovertool=False,
title="Histogramme des commentaires",
color='red',
line_color="white",
legend=False,
# normed=100,
)
Regardons quelques commentaires
(df.sort_values(by='Longueur des commentaires',ascending=False)
[['Episode','content','Longueur des commentaires','nick','hwlevel']].head(3)
.style.hide_index()
)
Je dirais,C'est là que le commentaire a été copié.,C'est un génie.?
.Regardons quelques - uns des plus appréciés
# pd.set_option('display.max_colwidth',1000)
(df.sort_values(by='up',ascending=False)
[['Episode','content','up','nick','hwlevel']].head()
.style.hide_index()
)
Voir la carte Ne te perds pas.
!C'est un pédoncule??Super.8000
C'est super.~~
user_comment_num = df.groupby('userid').agg(Nombre de commentaires=('id','nunique'),
vipGrade=('hwlevel','max')
).reset_index()
user_comment_num.sort_values(by='Nombre de commentaires',ascending=False).head()
userid | Nombre de commentaires | vipGrade |
---|---|---|
640014751 | 33 | 5 |
1368145091 | 24 | 1 |
1214181910 | 18 | 3 |
1305770517 | 17 | 2 |
1015445833 | 14 | 5 |
Évaluation33
Article (s),L'utilisateur est très bon aussi.!!Voyons ce qu'il a dit.:
df.query('userid==640014751')[['nick','Episode','time','content']].sort_values(by='time')
C'est un peu ennuyeux.,C'est une bonne nouvelle.!!Regardons le deuxième plus grand nombre de petits partenaires!
df.query('userid==1368145091')[['nick','Episode','time','content']].sort_values(by='time')
Je dois dire,C'est normal...Mais,Je me sens un peu bavard.,Ha Ha!!
C'est quoi, ces deux - là?,Regarde ça avec intérêt.:
from skimage import io
# Afficher l'image de la tête
img_url = df.query('userid==640014751')['head'].iloc[0]
image = io.imread(img_url)
io.imshow(image)
from skimage import io
# Afficher l'image de la tête
img_url = df.query('userid==1368145091')['head'].iloc[0]
image = io.imread(img_url)
io.imshow(image)
Toux,Je ne ferai pas d'évaluation.,Après tout, ma tête et mon surnom sont très bons.…
Référence à cette section《》,Nous allons commencer par le nuage de mots entiers et les parties du nuage de mots principaux
Voyons d'abord combien de fois nos trois personnages principaux ont parlé
df.fillna('',inplace=True)
hu = ['Lao Hu.','Merde!','Pan Yueming','Hu','Pan!']
yang = ['Zhang Yuqi','Shirley','Yang.']
wang = ['Jiang Chao','Le gros']
df_hu = df[df['content'].str.contains('|'.join(hu))]
df_yang = df[df['content'].str.contains('|'.join(yang))]
df_wang = df[df['content'].str.contains('|'.join(wang))]
df_star = pd.DataFrame({
'Rôle':['Merde!','ShirleyYang.','Chubby Wang.'],
'Poids':[len(df_hu),len(df_yang),len(df_wang)]
})
y = df_star['Poids']
mapper = linear_cmap(field_name='Poids', palette=Spectral[11] ,low=min(y) ,high=max(y))
df_star_bar = df_star.plot_bokeh.bar(
x = 'Rôle',
y = 'Poids',
ylabel="Poids de référence",
title="Poids de référence du rôle principal",
color=mapper,
alpha=0.8,
legend=False
)
Le gros Wang sourit.,Je dois dire que c'est très fréquent.!!!
Nuage de mots entiers
Hu Ba word cloud
ShirleyYang ciyun
Wang chuzi ci Yun
Word cloud Core Code
import os
import stylecloud
from PIL import Image
import jieba
import jieba.analyse
import pandas as pd
from wordcloud import STOPWORDS
def ciYun(data,addWords,stopWords):
print('Dessin en cours...')
comment_data = data
for addWord in addWords:
jieba.add_word(addWord)
comment_after_split = jieba.cut(str(comment_data), cut_all=False)
words = ' '.join(comment_after_split)
# Mots désactivés par word cloud
stopwords = STOPWORDS.copy()
for stopWord in stopWords:
stopwords.add(stopWord)
# Juste le code ci - dessous.,Vous pouvez obtenir des paramètres qui répondent aux exigences de type
stylecloud.gen_stylecloud(
text=words,
size = 800,
palette='tableau.BlueRed_6', # Définir le schéma de couleurs
icon_name='fas fa-mountain',# paper-plane mountain thumbs-up male fa-cloud
custom_stopwords = stopwords,
font_path='FZZJ-YGYTKJW.TTF'
# bg = bg,
# font_path=font_path, # Carte des nuages Police(Le chinois doit être réglé à la police chinoise disponible sur cet ordinateur)
)
print('Mot Cloud généré~')
pic_path = os.getcwd()
print(f'Le fichier word cloud Map a été enregistré dans {
pic_path}')
data = df.content.to_list()
addWords = ['M. PAN.','Yunnan Worm Valley','Degré de réduction',
'Lao Hu.','Merde!','Pan Yueming',
'Zhang Yuqi','Shirley','ShirleyYang.','Officier Yang',
'Chubby Wang.','Le gros']
# Ajouter un mot de désactivation
stoptxt = pd.read_table(r'stop.txt',encoding='utf-8',header=None)
stoptxt.drop_duplicates(inplace=True)
stopWords = stoptxt[0].to_list()
words = ['Dis - le.','Année','VIP','C'est vrai.','C'est','- Non.','Merde!','Comme si']
stopWords.extend(words)
# Exécution~
ciYun(data,addWords,stopWords)
C'est tout ce qui précède,Si vous êtes intéressé,C'est bien.+Je regarde,Retour en arrière - plan 210905
Code de réception+Données!
版权声明:本文为[Appelez - moi frère.]所创,转载请带上原文链接,感谢。 https://pythonmana.com/2022/01/202201080611484662.html