Vous n'êtes pas identifié(e).
Je suis tombé par hasard sur cette video et je me suis dit que son script au monsieur était vraiment sympa et pas trop mal pensé en vue de récupérer proprement de la data search console, surtout si certains d'entre vous ont à faire du reporting. La vidéo en anglais: https://youtu.be/oiQ0EYAEl-Y
Je crois que c'est un québecois, j'ai pas poussé le vice à aller sur son site s'il y a une version en québécois, je poste ça ici avant d'oublier
🔴 Hors ligne
j'utilise l'api et c'est énorme tous les mots clés que l'on récupère
Envie de me faire plaisir , achetez les mêmes proxys que j'utilise via ce lien : -=[ buyproxies.org ]=- (15€ pour 10 proxys dédiés)
Envie de tester ZennoPoster c'est par ici : -=[ ZennoPoster ]=- (à partir de 87$)
🔴 Hors ligne
🔴 Hors ligne
j'utilise l'api et c'est énorme tous les mots clés que l'on récupère
Yes. Une vrai mine d'or avec de la data bien plus précise que celle des outils tiers
Data studio ne fait pas le job ?
L'intérêt de l'API c'est surtout ce qu'on peut ressortir de la donnée GSC après raffinage/manipulation. Tu peux vraiment sortir de la data raffinée qui vaut de l'or de manière automatique (cannibalisation, couplage avec Trends, extrapolation intention de recherche, etc...).
🔴 Hors ligne
Oui encore faut-il savoir traiter l'info comme cela semble être ton cas
N'hésite pas à faire un topic
Dernière modification par chn16000 (2020-11-22 10:04:10)
Soyez vous-même, les autres sont déjà pris
🔴 Hors ligne
Oui encore faut-il savoir traiter l'info comme cela semble être ton cas
N'hésite pas à faire un topic
Bien sûr je peux filer des bouts de code (après adaptation) pour certaines tâches! Un truc simple pour commencer, genre détection de la cannibalisation, évaluation du degré de gravité (temporelle, ranking), ça vous intéresse?
🔴 Hors ligne
Pour découvrir oui ça m'intéresse.
C'est le genre d'analyse dont je ne me suis jamais préoccupé. Donc curieux effectivement.
Soyez vous-même, les autres sont déjà pris
🔴 Hors ligne
OK, j'essaie de partager ça quand j'en aurai le temps. J'ai la mauvaise habitude de faire du code ad hoc pour des projets au lieu de créer des librairies qui peuvent être facilement être réutilisées ailleurs. Ce sont les travers de l'auto apprentissage Mais ça sera l'occasion de remettre quelques trucs au propre.
🔴 Hors ligne
En passant, je viens de tester le script en question et ça me fait penser à un truc à préciser, si vous souhaitez tirer sur l'API les données historiques d'un domaine assez riche en nombre de mots clés pour la première fois:
- pensez au stockage de la donnée : si vous exportez en csv par exemple, vous pouvez vous retrouver avec des dataframes de plusieurs dizaines ou centaines de millions de lignes (si vous débutez en Python, lancez vous sur Pandas, c'est top! Manipuler ce genre de data avec tableur, c'est même pas la peine d'essayer), avec un fichier de plusieurs (dizaines) de Go.
- pensez aux limitations de l'API (1200 requêtes/min max). Vu qu'une requête ne renvoie "que" 25000 lignes et que vous pouvez avoir 25000 x milliers de fois à récupérer pour chaque date, pensez à ajouter quelques lignes pour freiner les requêtes sinon vous allez manger des erreurs 403 rapidement (étonnant qu'il n'ai pas inclus ce garde fou à la base).
🔴 Hors ligne
Le thread est un peu vieux mais si ça peut servir à quelqu'un dernièrement j'ai utilisé l'API ici
https://github.com/joshcarty/google-searchconsole
Et ça marche plutôt et c'est facile à utiliser derrière avec pandas.
Créateur de tools SEO => 12pages.com (1 ou 2 pages pour ces 2 requêtes); SERPmantics.com (analyse sémantique)
🔴 Hors ligne
@poulpe_centriste
Up un peu ancien, un partage est toujours bienvenu ?
Plusieurs projets ecom thématique mode en ES/FR en cours. Venez me mp les vendeurs de liens propres
🔴 Hors ligne
Le thread est un peu vieux mais si ça peut servir à quelqu'un dernièrement j'ai utilisé l'API ici
https://github.com/joshcarty/google-searchconsole
Et ça marche plutôt et c'est facile à utiliser derrière avec pandas.
Sympa ça !
🔴 Hors ligne
@poulpe_centriste
Up un peu ancien, un partage est toujours bienvenu ?
oula le déterrage et rappel de promesse non tenue, bien vu
je vais aller farfouiller pouvoir ce qui peut être partageable (il me semble que j'avais partagé ailleurs le moyen de faire une "heatmap-timeline" genre ce qu'il y a chez Ahrefs via la data GSC dans un autre fil).
En tout cas la majorité de la data GSC a surtout servit à faire du mining de kw de première fraîcheur afin d'aller ensuite dans une pipeline dont le but est notamment de faire du clustering/étude de marché/définition de politique de contenu. Pas vraiment pour faire du bench si c'est ce que tu attends (ce qui me gave).
Depuis je n'ai plus travaillé sur l'API GSC car je me suis désengagé des activités dépendant de près ou loin de la vente en ligne pour aller vers des activités plus adaptées au contexte à venir tout en ayant emmené dans les bagages d'acquis et outils bien utiles.
N'oubliez pas que votre job c'est la théorie de l'information. Pas l'optimisation pour Google. Votre rémunération ne doit pas dépendre d'un marché façonné par certains acteurs, mais de votre force de travail.
🔴 Hors ligne
Après plusieurs moi j'y repense en fouillant dans les scripts python;
de ce que je peux filer déjà de but en blanc et réutilisable par tout le monde;
Script basique qui récupère pour chaque page les perfs GSC dans un fichier CSV, à adapter selon le type de BDD que vous utilisez:
import pandas as pd
import os
import pickle
from datetime import datetime, timedelta
# Scopes
SCOPES = ['https://www.googleapis.com/auth/webmasters.readonly']
def get_credentials():
creds = None
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file('client_secret.json', SCOPES)
creds = flow.run_console()
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
return creds
def fetch_data(webmasters_service, start_date, end_date, data_file='get_all_gsc_data_bypage.csv', tmp_file='temp_dates.csv'):
if os.path.exists(tmp_file):
fetched_dates = pd.read_csv(tmp_file)['date'].tolist()
else:
fetched_dates = []
date_range = [dt.strftime('%Y-%m-%d') for dt in rrule(DAILY, dtstart=parse(start_date), until=parse(end_date))]
missing_dates = list(set(date_range) - set(fetched_dates))
if not missing_dates:
print(f"All data for dates between {start_date} to {end_date} already fetched")
return []
for date in missing_dates:
request = {
'startDate': date,
'endDate': date,
'dimensions': ['date', 'page', 'query'],
'searchType': 'web',
'aggregationType': 'auto',
'rowLimit': 25000
}
response = webmasters_service.searchanalytics().query(siteUrl='https://*****', body=request).execute()
if 'rows' not in response:
print(f"No data for {date}")
else:
data = []
for row in response['rows']:
data.append({
'date': row['keys'][0],
'page': row['keys'][1],
'query': row['keys'][2],
'position': row['position'],
'clicks': row['clicks'],
'impressions': row['impressions'],
'ctr': row['ctr']
})
df = pd.DataFrame(data)
if os.path.exists(data_file):
df.to_csv(data_file, mode='a', header=False, index=False)
else:
df.to_csv(data_file, mode='w', header=True, index=False)
fetched_dates.append(date)
pd.DataFrame({'date': fetched_dates}).to_csv(tmp_file, index=False)
return data
creds = get_credentials()
# Appel Search Console API
webmasters_service = build('webmasters', 'v3', credentials=creds)
# Definition du delta dates
end_date = datetime.now() # Fetch data up to today
start_date = (end_date - relativedelta(months=16)) # Set your desired start date to be 16 months prior to today
start_date_str = start_date.strftime("%Y-%m-%d")
end_date = end_date.strftime('%Y-%m-%d')
print(start_date_str, end_date)
fetch_data(webmasters_service, start_date_str, end_date)
Modifier bien sur "(siteUrl='https://*****', body=request).execute()" par votre url de domaine désiré. Vous trouverez des milliers de tutos sur comment utiliser l'API GSC.
Comme la GSC a la manie de considerer les # dans les URL comme des pages à part, un script pour nettoyer les URL et fusionner page#1.html avec page.html:
def clean_filename(filename):
"""
Nettoyage filename
"""
filename = re.sub(r'\W+', '_', filename) # Remplace non alphanumerique par underscore
filename = filename.strip('_') # Retire underscores
return filename
# Chargement du CSV
df = pd.read_csv('keywords2.csv')
# Création 'base_url' qui contient l'url avant '#'
df['base_url'] = df['url'].apply(lambda x: urlparse(x).scheme + "://" + urlparse(x).netloc + urlparse(x).path)
# Regroupement par base_url
grouped_by_url = df.groupby('base_url')
# Creation dossier pour les csv
os.makedirs('url_csvs', exist_ok=True)
# Creation fichiers csv
for url, group_df in grouped_by_url:
group_df = group_df.drop(columns=['url', 'base_url'])
filename = clean_filename(url) + '.csv'
file_path = os.path.join('url_csvs', filename)
group_df.to_csv(file_path, index=False)
Code pour générer des heatmaps de mots clés pour chaque page à partir des données GSC, à la mode Ahrefs. Désolé pour l'intég du JS si y'a des bons en JS ou dérivés, qu'ils optimisent. Cette partie est celle à le plus adapter à vos besoins ou dashboards. Là je file la version de base: 1 page GSC = 1 fichier html généré dans un dossier, à vous de gérer l'intégration dans vos outils maison surtout coté récupération de la data csv vu que c'est codé en dur dans cet exemple. A chacun sa méthode pour le front.
A suivre. Je verrai si je file du code pour faire du clustering. Si y'a des gens que ça dérange parce qu'ils en font un business (désolé je ne suis plus trop le SEO donc je ne sais plus vraiment ce qui se fait mais je me doute que ce genre de truc doit désormais être proposé en SAAS) je ne le mettrai pas par respect.
template_string = """
<!DOCTYPE html>
<html>
<head>
<title>Heatmap Visualization</title>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/heatmap.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/data.js"></script>
<script src="https://code.highcharts.com/modules/boost-canvas.js"></script>
<script src="https://code.highcharts.com/modules/boost.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<style>
.highcharts-figure, .highcharts-data-table table {
min-width: 360px;
max-width: 1000px;
margin: 1em auto;
}
.highcharts-data-table table {
font-family: Verdana, sans-serif;
border-collapse: collapse;
border: 1px solid #EBEBEB;
margin: 10px auto;
text-align: center;
width: 100%;
max-width: 500px;
}
.highcharts-data-table caption {
padding: 1em 0;
font-size: 1.2em;
color: #555;
}
.highcharts-data-table th {
font-weight: 600;
padding: 0.5em;
}
.highcharts-data-table td, .highcharts-data-table th, .highcharts-data-table caption {
padding: 0.5em;
}
.highcharts-data-table thead tr, .highcharts-data-table tr:nth-child(even) {
background: #f8f8f8;
}
.highcharts-data-table tr:hover {
background: #f1f7ff;
}
</style>
</head>
<body>
<figure class="highcharts-figure">
<div id="container"></div>
<p class="highcharts-description">
Ton texte
</p>
</figure>
<pre id="csv" style="display: none">{{ csv_data }}</pre>
<script>
Highcharts.chart('container', {
data: {
csv: document.getElementById('csv').innerHTML
},
chart: {
type: 'heatmap'
},
boost: {
useGPUTranslations: true
},
title: {
text: 'Highcharts heat map',
align: 'left',
x: 40
},
subtitle: {
text: 'Rankings',
align: 'left',
x: 40
},
xAxis: {
type: 'datetime',
min: Date.UTC(2022, 2, 10),
max: Date.UTC(2023, 6, 02, 23, 59, 59),
labels: {
align: 'left',
x: 5,
y: 10,
format: '{value:%d-%m-%y}' // long month
},
showLastLabel: false,
tickLength: 16
},
yAxis: {
title: {
text: 'position'
},
labels: {
format: '{value}'
},
minPadding: 0,
maxPadding: 0,
startOnTick: false,
endOnTick: false,
tickPositions: [1, 5, 10, 15, 20, 30, 40, 50, 70, 100],
tickWidth: 1,
min: 1,
max: 100,
reversed: true
},
colorAxis: {
stops: [
[0, '#ffffff'],
[0.01, '#98c0e3'],
[0.1, '#3892e0'],
[0.2, '#f7a840'],
[0.5, '#f7c040'],
[1, '#f24f0f']
],
min: 1,
max: 350,
startOnTick: true,
endOnTick: false,
labels: {
format: '{value}'
}
},
series: [{
boostThreshold: 100,
borderWidth: 0,
nullColor: '#EFEFEF',
colsize: 24 * 36e5, // one day
tooltip: {
headerFormat: 'kw<br/>',
pointFormat: '{point.x:%e %b, %Y} {point.y}: <b>{point.value} mots clés</b>'
},
turboThreshold: Number.MAX_VALUE // #3404, remove after 4.0.5 release
}]
});
</script>
</body>
</html>
"""
output_dir = "/url_csvs"
# Fetch all CSV files from the folder.
csv_files = [f for f in os.listdir(output_dir) if f.endswith('.csv')]
# Load the Jinja2 template.
template = jinja2.Template(template_string)
# Loop over each CSV file and create an HTML file for it.
for csv_file in csv_files:
df = pd.read_csv(os.path.join(output_dir, csv_file))
# Prepare the CSV data for the HTML template.
csv_data = df.to_csv(index=False)
# Render the HTML with the CSV data.
html = template.render(csv_data=csv_data)
# Write the HTML to a new .html file.
with open(os.path.join(output_dir, f"/{csv_file}.html"), 'w') as f:
f.write(html)
🔴 Hors ligne