🢂IndexNow i Indexing API czyli natychmiastowe indeksowanie serwisu WWW ‑ Skrypty w Python

Używając tych skryptów w python, możesz zaindeksować swoją stronę w wynikach wyszukiwania praktycznie natychmiast.

Skrypty, służą do automatycznego zgłaszania ze strony internetowej (pobiera dane z sitemap) do systemu indeksowania wyszukiwarkek Bing i Google, wykorzystując protokół IndexNow i Indexing API. Jest to przydatne w przypadku, gdy chcesz, aby nowe treści na twojej stronie były szybko odkryte i zindeksowane, co może przyspieszyć ich pojawienie się w wynikach wyszukiwania. Z testów wynika że w przeciągu kilku minut cała zawartość na poziomie 10 tysięcy podstron pojawia się w Google.

Co dokładnie robią skrypty?

  1. Pobieranie pliku sitemap: Skrypt zaczyna od pobrania pliku sitemap.xml, który zazwyczaj zawiera listę wszystkich dostępnych URL-i na stronie internetowej. Plik ten jest używany przez wyszukiwarki do lepszego rozumienia struktury witryny.
  2. Analiza pliku sitemap: Po pobraniu, skrypt parsuje plik XML, aby wyodrębnić z niego URL-e. Sitemap XML jest standardem i zazwyczaj stosuje określone schematy nazw, które skrypt musi rozpoznać, aby prawidłowo odczytać URL-e.
  3. Wysyłanie żądania POST: Następnie skrypt zbiera te URL-e i przygotowuje z nich listę (do 10 000 URL-i na żądanie), którą przesyła do systemu IndexNow poprzez żądanie HTTP POST w formacie JSON. Żądanie to jest wysyłane na serwer wyszukiwarki, z którym chcesz się komunikować (np. Bing).
  4. Przetwarzanie odpowiedzi: Skrypt również sprawdza odpowiedź od serwera wyszukiwarki, co pozwala zobaczyć, czy zgłoszenie URL-i zakończyło się sukcesem, czy też wystąpiły jakieś problemy.

Jak go uruchomić

Aby uruchomić skrypt Pythona, który automatycznie zgłasza URL-e do systemu IndexNow czy Indexing API, potrzebujesz spełnić kilka podstawowych warunków i wykonać następujące kroki:

Wymagania:

  1. Python: Upewnij się, że masz zainstalowanego Pythona na swoim komputerze. Możesz go pobrać i zainstalować z oficjalnej strony Pythona.
  2. Biblioteka Requests: Musisz mieć zainstalowaną bibliotekę requests, którą możesz zainstalować lub zaktualizować za pomocą polecenia pip. Otwórz terminal lub wiersz poleceń i wpisz:
pip install requests

Uruchamianie skryptu:

  1. Zapisz skrypt: Zapisz powyższy kod w pliku o rozszerzeniu .py, na przykład indexnow_submitter.py. Możesz użyć dowolnego edytora tekstu, takiego jak Notepad++ czy Visual Studio Code, do stworzenia tego pliku.
  2. Otwórz terminal: Otwórz wiersz poleceń lub terminal na swoim komputerze. Następnie przejdź do katalogu, w którym zapisałeś plik skryptu. Możesz to zrobić za pomocą polecenia cd ścieżka_do_folderu. Na przykład:
cd C:\Users\TwojeImie\Documents\
  1. Uruchom skrypt: Po przejściu do odpowiedniego katalogu, uruchom skrypt za pomocą polecenia:
python indexnow_submitter.py

Co warto sprawdzić przed uruchomieniem:

  • Dostosuj URL sitemap i wyszukiwarkę: Upewnij się, że zmieniłeś w skrypcie adres URL pliku sitemap (sitemap_url) na adres prowadzący do faktycznego pliku sitemap twojej strony. Ponadto, jeśli chcesz użyć innej wyszukiwarki wspierającej IndexNow niż Bing, zmień wartość search_engine na odpowiednią nazwę hosta.
  • Klucz IndexNow: W skrypcie jest użyty przykładowy klucz dla key. Musisz zastąpić go prawdziwym kluczem, który uzyskasz, rejestrując się w usłudze IndexNow dla twojej strony.

Po wykonaniu tych kroków, skrypt powinien zacząć wysyłać URL-e do wybranej wyszukiwarki, co możesz zweryfikować obserwując odpowiedzi w terminalu. Jeśli napotkasz błędy, sprawdź komunikaty błędów dla wskazówek, co poszło nie tak, i odpowiednio dostosuj kod lub konfigurację.

Kod skryptu do Binga

import requests
import xml.etree.ElementTree as ET

# Konfiguracja
sitemap_url = 'https://www.example.com/sitemap.xml'
search_engine = 'api.indexnow.org'
host_name = "www.example.com"
key = "5e98e8a534564a618fe410f7b37ba664"
# key_location = "https://www.example.com/5e98e8a534564a618fe410f7b37ba664.txt"

def fetch_sitemap(url):
    response = requests.get(url)
    response.raise_for_status()  # Sprawdza, czy zapytanie się powiodło
    return response.text

def parse_sitemap(xml_content):
    root = ET.fromstring(xml_content)
    namespaces = {'ns': 'http://www.sitemaps.org/schemas/sitemap/0.9'}  # Dostosuj namespace do twojego sitemap
    url_list = [url.find('ns:loc', namespaces).text for url in root.findall('ns:url', namespaces)]
    return url_list

def submit_to_indexnow(url_list, search_engine_hostname):
    post_url = f'http://{search_engine_hostname}/indexnow'
    headers = {'Content-Type': 'application/json; charset=utf-8'}
    body = {
        "host": host_name,
        "key": key,
        # "keyLocation": key_location,
        "urlList": url_list
    }
    response = requests.post(post_url, json=body, headers=headers)
    return response.status_code, response.text

# Wykonanie funkcji
sitemap_content = fetch_sitemap(sitemap_url)
urls = parse_sitemap(sitemap_content)
status_code, response_text = submit_to_indexnow(urls[:10000], search_engine)  # Przesyła maksymalnie pierwsze 10000 URL-i

print(f"Status: {status_code}, Response: {response_text}")

Skrypt do Google

Ten kod służy do skomunikowania się z API Google Indexing, pobrania zawartości pliku XML (mapy witryny), analizy tej zawartości w celu uzyskania listy adresów URL i zgłoszenia tych adresów URL do API Google Indexing.

  1. Funkcja authenticate_with_google() autoryzuje dostęp do API Google Indexing poprzez użycie klucza usługi, który jest pobierany z pliku określonego w zmiennej SERVICE_ACCOUNT_FILE. Następnie tworzy się usługę zbudowaną na podstawie tego poświadczenia i zwraca ją.
  2. Funkcja fetch_sitemap(url) pobiera zawartość pliku XML (mapy witryny) z podanego URL-a przy użyciu biblioteki requests. Jeśli żądanie zakończy się niepowodzeniem, funkcja zgłasza wyjątek. Następnie zwraca zawartość jako tekst.
  3. Funkcja parse_sitemap(xml_content) analizuje zawartość XML mapy witryny, znajduje adresy URL w tej mapie i zwraca je jako listę.
  4. Funkcja submit_urls_to_google_indexing_api(service, url_list) przyjmuje usługę autoryzacji Google, listę adresów URL do zgłoszenia i iteruje po każdym adresie URL. Dla każdego adresu URL tworzy ciało żądania, które zawiera adres URL i typ zgłoszenia, a następnie wysyła żądanie do Google Indexing API. Otrzymaną odpowiedź drukuje na konsoli.

Na końcu kodu jest główna logika:

  1. Autoryzacja do API Google Indexing.
  2. Pobranie zawartości mapy witryny.
  3. Analiza mapy witryny w celu uzyskania listy adresów URL.
  4. Zgłoszenie tych adresów URL do API Google Indexing przy użyciu wcześniej autoryzowanej usługi.

Co warto wiedzieć przed uruchomieniem:

Dobry opis jak uzyskać klucz w JSON znajduje się na stronie wtyczki rankmath Skrypt dostosowujesz podobnie jak ten do Binga, zmieniając (SERVICE_ACCOUNT_FILE, sitemap_url).

Uruchamianie skryptu:

  1. Zapisz skrypt: Zapisz powyższy kod w pliku o rozszerzeniu .py, na przykład google_submitter.py. Możesz użyć dowolnego edytora tekstu, takiego jak Notepad++ czy Visual Studio Code, do stworzenia tego pliku.
  2. Otwórz terminal: Otwórz wiersz poleceń lub terminal na swoim komputerze. Następnie przejdź do katalogu, w którym zapisałeś plik skryptu. Możesz to zrobić za pomocą polecenia cd ścieżka_do_folderu. Na przykład:
cd C:\Users\TwojeImie\Documents\
  1. Uruchom skrypt: Po przejściu do odpowiedniego katalogu, uruchom skrypt za pomocą polecenia:
python google_submitter.py
from google.oauth2 import service_account
from googleapiclient.discovery import build
import xml.etree.ElementTree as ET
import requests

# Konfiguracja
# Definiujemy zakresy dostępu do API
SCOPES = ['https://www.googleapis.com/auth/indexing']

# Ścieżka do pliku z kluczem usługi
SERVICE_ACCOUNT_FILE = 'indexing-api.json'

# Adres URL sitemap.xml
sitemap_url = 'https://adreswww.pl/sitemap.xml'


def authenticate_with_google():
    """
    Uwierzytelnia się w Google API i zwraca zainicjowany serwis indexing.
    """
    # Tworzymy obiekt z klucza usługi
    credentials = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)
    # Inicjujemy serwis indexing z zainicjowanymi poświadczeniami
    service = build('indexing', 'v3', credentials=credentials)
    return service


def fetch_sitemap(url):
    """
    Pobiera treść sitemap.xml z podanego adresu URL.
    """
    response = requests.get(url)
    response.raise_for_status()
    return response.text


def parse_sitemap(xml_content):
    """
    Wyodrębnia z sitemap.xml listę URL.
    """
    root = ET.fromstring(xml_content)
    namespaces = {'ns': 'http://www.sitemaps.org/schemas/sitemap/0.9'}
    url_list = [url.find('ns:loc', namespaces).text for url in root.findall('ns:url', namespaces)]
    return url_list


def submit_urls_to_google_indexing_api(service, url_list):
    """
    Przesyła listę URL do API usługi indexing Google.
    """
    for url in url_list:
        # Tworzymy treść zapytania
        body = {
            'url': url,
            'type': 'URL_UPDATED'
        }
        # Przesyłamy zapytanie
        response = service.urlNotifications().publish(body=body).execute()
        print(f"Przesłano {url}: Odpowiedź {response}")


# Główna logika
google_service = authenticate_with_google()
sitemap_content = fetch_sitemap(sitemap_url)
urls = parse_sitemap(sitemap_content)
submit_urls_to_google_indexing_api(google_service, urls)

Problemy z google_submitter.py

Błąd HttpError 403: Permission denied. Failed to verify the URL ownership sygnalizuje, że Google nie widzi Twojej aplikacji (a dokładniej – konta usługi) jako właściciela adresu URL, który próbujesz zgłosić. Oto kroki, które zwykle rozwiązują problem:


1. Zweryfikuj witrynę w Google Search Console

  1. Dodaj właściwość (najbezpieczniej „Domena” – obejmuje wszystkie protokoły i subdomeny).
  2. Zakończ weryfikację (DNS TXT lub inna metoda).

Jeśli ta część jest już zrobiona, przejdź dalej. Google for Developers


2. Nadaj uprawnienia konto-usłudze (service account)

  1. W Search Console otwórz Ustawienia → Użytkownicy i uprawnienia.
  2. Kliknij trzy kropki przy swoim wpisie i wybierz Zarządzaj właścicielami.
  3. W sekcji Zweryfikowani właściciele kliknij Dodaj właściciela.
  4. Wprowadź adres konta usługi w formacie moja-usluga@moj-projekt.iam.gserviceaccount.com.
  5. Zapisz i poczekaj kilka minut, aż status zmieni się na „Zweryfikowano”. Google for Developers

Uwaga: Jeśli konto usługi ma tylko rolę „Użytkownik” lub „Pełny dostęp”, Indexing API nadal zwróci 403. Musi być właścicielem.


3. Upewnij się, że zgłaszany URL należy do tej samej właściwości

  • Protokół (https:// vs http://), subdomena (www. / bez) i ścieżka muszą pasować do zweryfikowanej właściwości. Inaczej – 403. Google for Developers

4. Sprawdź konfigurację projektu Google Cloud

  1. W konsoli Cloud włącz Indexing API dla projektu, z którego pochodzi konto usługi.
  2. Plik credentials.json używany w skrypcie musi pochodzić z tego samego konta usługi.
  3. Skrypt powinien uwierzytelniać się przy pomocy OAuth 2.0 service account bez dodatkowych zakresów – biblioteka googleapiclient robi to domyślnie.

5. Potwierdź, że Twoje strony spełniają wymagania Indexing API

Od 2024 r. API jest oficjalnie przeznaczone wyłącznie do stron z JobPosting albo BroadcastEvent w VideoObject. Zgłaszanie innych typów URL nie jest blokowane technicznie, ale narusza wytyczne i może prowadzić do ograniczenia albo błędów. Google for Developers


6. Przykładowy minimalny skrypt testowy

from google.oauth2 import service_account
from googleapiclient.discovery import build

SCOPES = ["https://www.googleapis.com/auth/indexing"]
SERVICE_ACCOUNT_FILE = "credentials.json"

creds = service_account.Credentials.from_service_account_file(
    SERVICE_ACCOUNT_FILE, scopes=SCOPES)

service = build('indexing', 'v3', credentials=creds)

body = {
    "url": "https://example.com/oferta-pracy-123",
    "type": "URL_UPDATED"
}
response = service.urlNotifications().publish(body=body).execute()
print(response)

Jeśli uprawnienia są poprawne, zwróci status NOT_COMPLETE. 403 oznacza dalej problem z własnością.


Podsumowanie

  1. Zweryfikuj domenę w Search Console.
  2. Dodaj konto usługi jako właściciela tej właściwości.
  3. Sprawdź, czy URL należy do tej samej właściwości.
  4. Upewnij się, że API jest włączone w Google Cloud i używasz właściwych poświadczeń.
  5. Jeśli strona nie zawiera JobPosting/BroadcastEvent, rozważ tradycyjne metody (mapa witryny, ping sitemaps).

Po wykonaniu powyższych kroków wywołanie service.urlNotifications().publish() powinno zacząć zwracać kod 200 zamiast 403.