Google Indexing API: давайте разжуем как делать все просто своими руками на PHP

1 234 5
C
На сайте с 04.02.2005
Offline
291
#21
minsky #:
А Google indexing бота запускает мгновенно
Если... Вам это позволили, Сейчас это не происходит (((
minsky
На сайте с 01.09.2012
Offline
190
#22
Chukcha #:
Если... Вам это позволили, Сейчас это не происходит (((
Уже писал тут, позволяет всем, просто нужно правильно настроить)))
Продвигаю сайты ссылками, ускоряю индексацию сайтов и отдельных страниц ( https://kwork.ru/user/minsky?ref=23382 )
K
На сайте с 14.01.2025
Offline
10
#23

У меня свой скрипт на Python, который берет ссылки из URL и отправляет в Indexing API. Я делал скрипт, который при обновлении страницы слал запрос. Толку — 0. Может, он в очередь добавляет где-то себе, но точно не моментально запускает Google-бота. А все эти скрипты отличаются лишь языком, а запросы у всех одни :)

Genius Ideaing
На сайте с 12.02.2024
Offline
68
#24
Kuala #:
У меня свой скрипт на Python, который берет ссылки из URL и отправляет в Indexing API. Я делал скрипт, который при обновлении страницы слал запрос. Толку — 0.

выложите пожалуйста этот скриптик на Пайтон...

я его перепишу на ПэХаПэ...

очень нужно... 

Дешёвый хостинг и домены: https://clck.ru/3FxXCa / Мощный хостинг: https://clck.ru/3DKmVu / Есть Идеи! Ищу хороших людей для реализации этих идей! Мой Telegram: https://clck.ru/396JFF
K
На сайте с 14.01.2025
Offline
10
#25
Genius Ideaing #:

выложите пожалуйста этот скриптик на Пайтон...

я его перепишу на ПэХаПэ...

очень нужно... 

Так а смысл какой. но если ты так хочешь

import json
import time
import logging
from datetime import datetime
from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
import os

class GoogleIndexingAPI:
    def __init__(self, service_account_file: str, urls_file: str, log_file: str = 'indexing.log'):
        self.service_account_file = service_account_file
        self.urls_file = urls_file
        
        
        logging.basicConfig(
            filename=log_file,
            level=logging.INFO,
            format='[%(asctime)s] [%(levelname)s] %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S'
        )
        self.logger = logging.getLogger(__name__)
        
        
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)
        formatter = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s')
        console_handler.setFormatter(formatter)
        self.logger.addHandler(console_handler)

    def get_authenticated_session(self):
        try:
            credentials = service_account.Credentials.from_service_account_file(
                self.service_account_file,
                scopes=['https://www.googleapis.com/auth/indexing']
            )
            
            session = AuthorizedSession(credentials)
            self.logger.info(f"Successfully authenticated with service account")
            return session
            
        except Exception as e:
            self.logger.error(f"Authentication failed: {str(e)}")
            return None

    def submit_url(self, session, url: str):
        api_url = 'https://indexing.googleapis.com/v3/urlNotifications:publish'
        
        data = {
            'url': url,
            'type': 'URL_UPDATED'
        }
        
        try:
            self.logger.info(f"Submitting URL to index: {url}")
            response = session.post(api_url, json=data)
            
            if response.status_code == 200:
                response_data = response.json()
                if ('urlNotificationMetadata' in response_data and
                    'url' in response_data['urlNotificationMetadata'] and
                    response_data['urlNotificationMetadata']['url'] == url):
                    self.logger.info(f"Successfully submitted URL: {url}")
                    return True
                else:
                    self.logger.warning(f"URL mismatch in response for: {url}")
                    return False
            else:
                self.logger.error(f"Failed to submit URL {url}. Status code: {response.status_code}")
                self.logger.error(f"Response: {response.text}")
                return False
                
        except Exception as e:
            self.logger.error(f"Error submitting URL {url}: {str(e)}")
            return False

    def process_urls(self):
        if not os.path.exists(self.urls_file):
            self.logger.error(f"URLs file not found: {self.urls_file}")
            return
            
        session = self.get_authenticated_session()
        if not session:
            return
            
        try:
            with open(self.urls_file, 'r') as f:
                urls = [line.strip() for line in f if line.strip()]
                
            self.logger.info(f"Found {len(urls)} URLs to process")
            
            successful_urls = []
            failed_urls = []
            
            for url in urls:
                if self.submit_url(session, url):
                    successful_urls.append(url)
                else:
                    failed_urls.append(url)
                time.sleep(1)  
            
            
            if failed_urls:
                failed_file = 'failed_urls.txt'
                with open(failed_file, 'w') as f:
                    for url in failed_urls:
                        f.write(f"{url}\n")
                self.logger.info(f"Failed URLs written to {failed_file}")
            
            self.logger.info(f"Processing complete. Success: {len(successful_urls)}, Failed: {len(failed_urls)}")
            
        except Exception as e:
            self.logger.error(f"Error processing URLs: {str(e)}")

if __name__ == "__main__":
    # Configuration
    SERVICE_ACCOUNT_FILE = "service-account.json"  # путь к файлу джсон
    URLS_FILE = "urls.txt"  # файл с урлами страним
    LOG_FILE = "indexing.log"  # лог файл
    
    indexer = GoogleIndexingAPI(SERVICE_ACCOUNT_FILE, URLS_FILE, LOG_FILE)
    indexer.process_urls()
S3
На сайте с 29.03.2012
Offline
341
#26
Kuala #:
Так а смысл какой. но если ты так хочешь

Хочешь ревью? На Пайтоне так не пишут))) 

C
На сайте с 04.02.2005
Offline
291
#27
Genius Ideaing #:

выложите пожалуйста этот скриптик на Пайтон...

я его перепишу на ПэХаПэ...

очень нужно... 

Зачем? Если Г не отдает ответ url_update с  сентября прошлого года
Если ранее, бот прибегал почти мгновенно

K
На сайте с 14.01.2025
Offline
10
#28
Sly32 #:

Хочешь ревью? На Пайтоне так не пишут))) 

какая разница если оно работает?)

S
На сайте с 18.11.2011
Offline
98
#29
Sly32 #:

Хочешь ревью? На Пайтоне так не пишут))) 

а что не так?
S3
На сайте с 29.03.2012
Offline
341
#30
sumpsonb #:
а что не так?

Для начала:

parser/index_api.py:1:1: F401 'json' imported but unused
parser/index_api.py:4:1: F401 'datetime.datetime' imported but unused
parser/index_api.py:9:1: E302 expected 2 blank lines, found 1
parser/index_api.py:13:1: W293 blank line contains whitespace
parser/index_api.py:14:1: W293 blank line contains whitespace
parser/index_api.py:15:9: E303 too many blank lines (2)
parser/index_api.py:22:1: W293 blank line contains whitespace
parser/index_api.py:23:1: W293 blank line contains whitespace
parser/index_api.py:24:9: E303 too many blank lines (2)
parser/index_api.py:36:1: W293 blank line contains whitespace
parser/index_api.py:38:30: F541 f-string is missing placeholders
parser/index_api.py:40:1: W293 blank line contains whitespace
parser/index_api.py:47:1: W293 blank line contains whitespace
parser/index_api.py:52:1: W293 blank line contains whitespace
parser/index_api.py:56:1: W293 blank line contains whitespace
parser/index_api.py:59:64: W504 line break after binary operator
parser/index_api.py:59:67: W291 trailing whitespace
parser/index_api.py:60:71: W504 line break after binary operator
parser/index_api.py:60:74: W291 trailing whitespace
parser/index_api.py:61:21: E129 visually indented line with same indent as next logical line
parser/index_api.py:71:1: W293 blank line contains whitespace
parser/index_api.py:80:1: W293 blank line contains whitespace
parser/index_api.py:84:1: W293 blank line contains whitespace
parser/index_api.py:88:1: W293 blank line contains whitespace
parser/index_api.py:90:1: W293 blank line contains whitespace
parser/index_api.py:93:1: W293 blank line contains whitespace
parser/index_api.py:99:30: W291 trailing whitespace
parser/index_api.py:100:1: W293 blank line contains whitespace
parser/index_api.py:101:1: W293 blank line contains whitespace
parser/index_api.py:102:13: E303 too many blank lines (2)
parser/index_api.py:108:1: W293 blank line contains whitespace
parser/index_api.py:110:1: W293 blank line contains whitespace
parser/index_api.py:114:1: E305 expected 2 blank lines after class or function definition, found 1
parser/index_api.py:119:1: W293 blank line contains whitespace
parser/index_api.py:121:27: W292 no newline at end of file

Это арбнет может позволить себе писать не соблюдая кодстайл и не думая как там потом интерпретатор будет корячится. Правда, допускаю что что-то из этого - из-за ошибки копирования.
Теперь по замечаниям:
- Логгер не нужно пихать в класс - это нарушает бизнес логику, не дает его переиспользовать,  возникаю сложности с тестированием. 
- Хорошая практика обьявлять сессию как контекст-менеджер. Нужно обьяснять зачем? 
- один метод - одно действие. вспоминаем SOLID. поэтому разбиваем process_urls. В черновом варианте примерно так:

import json
import time
import logging
from datetime import datetime
from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
import os
from contextlib import contextmanager
from typing import List, Tuple, Optional

def setup_logger(name: str, log_file: str) -> logging.Logger:
    """Configure and return a logger with file and console handlers."""
    logger = logging.getLogger(name)
    logger.setLevel(logging.INFO)
    
    if not logger.handlers:
        # File handler
        file_handler = logging.FileHandler(log_file)
        file_handler.setFormatter(
            logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s',
                            datefmt='%Y-%m-%d %H:%M:%S')
        )
        logger.addHandler(file_handler)
        
        # Console handler
        console_handler = logging.StreamHandler()
        console_handler.setFormatter(
            logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s')
        )
        logger.addHandler(console_handler)
    
    return logger

class GoogleIndexingAPI:
    def __init__(self, service_account_file: str, urls_file: str, logger: logging.Logger):
        self.service_account_file = service_account_file
        self.urls_file = urls_file
        self.logger = logger

    @contextmanager
    def get_authenticated_session(self):
        """Context manager for handling authenticated sessions."""
        try:
            credentials = service_account.Credentials.from_service_account_file(
                self.service_account_file,
                scopes=['https://www.googleapis.com/auth/indexing']
            )
            session = AuthorizedSession(credentials)
            self.logger.info("Successfully authenticated with service account")
            yield session
        except Exception as e:
            self.logger.error(f"Authentication failed: {str(e)}")
            yield None
        finally:
            if session:
                session.close()

    def submit_url(self, session: AuthorizedSession, url: str) -> bool:
        """Submit a single URL for indexing."""
        api_url = 'https://indexing.googleapis.com/v3/urlNotifications:publish'
        data = {'url': url, 'type': 'URL_UPDATED'}
        
        try:
            self.logger.info(f"Submitting URL to index: {url}")
            response = session.post(api_url, json=data)
            
            if response.status_code == 200:
                response_data = response.json()
                if self._validate_response(response_data, url):
                    self.logger.info(f"Successfully submitted URL: {url}")
                    return True
            
            self.logger.error(f"Failed to submit URL {url}. Status: {response.status_code}")
            return False
            
        except Exception as e:
            self.logger.error(f"Error submitting URL {url}: {str(e)}")
            return False

    def _validate_response(self, response_data: dict, url: str) -> bool:
        """Validate the API response data."""
        return ('urlNotificationMetadata' in response_data and
                'url' in response_data['urlNotificationMetadata'] and
                response_data['urlNotificationMetadata']['url'] == url)

    def _read_urls(self) -> List[str]:
        """Read URLs from file."""
        with open(self.urls_file, 'r') as f:
            return [line.strip() for line in f if line.strip()]

    def _save_failed_urls(self, failed_urls: List[str]) -> None:
        """Save failed URLs to file."""
        if failed_urls:
            failed_file = 'failed_urls.txt'
            with open(failed_file, 'w') as f:
                for url in failed_urls:
                    f.write(f"{url}\n")
            self.logger.info(f"Failed URLs written to {failed_file}")

    def process_urls(self) -> Tuple[int, int]:
        """Process all URLs from the input file."""
        if not os.path.exists(self.urls_file):
            self.logger.error(f"URLs file not found: {self.urls_file}")
            return (0, 0)
            
        try:
            urls = self._read_urls()
            self.logger.info(f"Found {len(urls)} URLs to process")
            
            successful_urls = []
            failed_urls = []
            
            with self.get_authenticated_session() as session:
                if not session:
                    return (0, 0)
                
                for url in urls:
                    if self.submit_url(session, url):
                        successful_urls.append(url)
                    else:
                        failed_urls.append(url)
                    time.sleep(1)
            
            self._save_failed_urls(failed_urls)
            self.logger.info(f"Processing complete. Success: {len(successful_urls)}, Failed: {len(failed_urls)}")
            return len(successful_urls), len(failed_urls)
            
        except Exception as e:
            self.logger.error(f"Error processing URLs: {str(e)}")
            return (0, 0)

def main():
    # Configuration
    SERVICE_ACCOUNT_FILE = "service-account.json"
    URLS_FILE = "urls.txt"
    LOG_FILE = "indexing.log"
    
    # Setup logger
    logger = setup_logger("google_indexing", LOG_FILE)
    
    # Initialize and run indexer
    indexer = GoogleIndexingAPI(SERVICE_ACCOUNT_FILE, URLS_FILE, logger)
    success, failed = indexer.process_urls()
    
    return success, failed

if __name__ == "__main__":
    main()

Ну и работать со сторонним апи в синхронном коде я бы вообще не стал. Использование threading ускорит работу минимум в 4 раза. 
это все так, навскидку. Если повозиться, можно еще пооптимизировать. 

1 234 5

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий