Sly32

Рейтинг
370
Регистрация
29.03.2012

alaev #:
А почему у тебя колесо оторвется от дороги? 😂😂

Мдя... Совсем тяжелый случай.


Ну на тебе схему совсем для детей и посчитай как изменится вектор направления  для обьекта А и В?

Можешь своими формулами.  Главное сопромат не забудь он же как раз тут к месту)))

не хаос #:
Валентина, человек с здоровой психикой никогда не будет оскорблять, хамить, вести себя неадекватно, поэтому не реагируйте на их выходки.

запомните этот твит))) в следующее твое хамство итд процитирую его тебе. 😂

юни #:
Как будто пиратство ограничивается только софтом, причём непременно платным.

Приведи примеры. Не забывай про тему топика(она есть в самом первом посте, если не знаешь как посмтреть,подсказываю)

Leema #:
рыночек порешает

Как связан рыночек с проблемой воровства? 

Leema #:
гнилую картошку я могу вернуть в магазин и забрать деньги

После сеанса в кино часто требуешь вернуть деньги? Если не устраивает Винда - то ты сносишь и не пользуешься ей?

alaev #:
А я такого и не говорил.

Ты наговорил столько бреда, примешал столько ненужного, что мне стыдно за твое образование. Мама с папой зря тратились))) Ты не умеешь логически мыслить и понимать примеры. Естественно, на самом деле система уравнений сложнее, в самом начале я говорил, что нужно учитывать, например параметры подвески - пружина+амортизатор. Потому что как только колесо оторвется от дороги, помимо ускорения свободного падения на него будут действовать и эти факторы. Но! это НЕ поменяет общий вектор расчета - увеличение скорости  уменьшает время прохождения ямы, соответственно уменьшается глубина погружения в яму, соответственно сила удара... 
У тебя же какие-то центры масс, цитаты из нейросети.... Тебя не учили любую задачу разбирать на простые составляющие, хотя это знают даже в школе. Ты отлично справляешься с обратным - нагромоздить ненужных фактов и в итоге не увидеть решения. Думаю это намеренный ход - ты так ведешь себя абсолютно во всех темах.

не хаос #:
Скажем даже так: параллельная вселенная для тех кому не нужны трансжиры, генномодифицированные продукты и химия. 

про тонны навоза не забудь сказать только, антибиотики если ты кур выращиваешь. Кучу удобрений под клубнику и прочее, без чего у тебя ничего не вырастет. Присмотрись к сортам помидоров и картошки, что у тебя растут - удивишься)

не хаос #:
Дача это свой мир, непосвященным в этот процесс ничего не понять и их там не ждут.

Ага, мир обгорелых на солнце задниц и белых животов, мошек, кротов на лужайках, черных ногтях, запаха навоза, горелого мяса, водки)))
Если что это шутка - это действительно другой мир и это надо любить. Мне понадобилось 17 лет чтобы понять что это не мое, хотя покупалась с мыслью проводить пенсию на свежем воздухе.

alaev #:
На велосипеде въехать в яму неравнозначно попаданию одного колеса автомобиля в яму. Учи физику!!!

Я в последний раз, чукча тебе пытаюсь обьяснить!!! Мы не сравниваем автомобиль и велосипед, автобус, танк, 6-осный грузовик или легковушку.
Разговор для разницы нагрузку на подвеску при проезде ямы на разной скорости одного типа  транспортного средства

На велике ты кульнешься в яму на скорости, автомобиль ее не заметит. Но сила удара по подвеске будет разной!!
А на определенной скорости колесо просто перелетит яму, вообще не получив удара! Это был вопрос Дмитрия и мои ответы основываются на нем. А не на ПДД, аэродинамике и прочей белиберде что ты приплел. 

Если уж и этот текст ты не в состоянии прочитать - умываю руки, медицина тут бессильна.

Vladimir #:
Дача это диагноз...для поясницы. Впрочем как и гири)

с 2005 года все лето проводил на даче. Если выходные, то в пятницу заехал, в воскр - вернулся. С утра корячишься на огороде, ругаешься с тещей, когда она выкопала яму на твоей лужайке или под гамаком посадила морковку. Вечером баня и обжирание горелым мясом. Пару раз удается выбраться по грибы... Обычно приезжаешь в воскресенье замордованый по самое не хочу. А, забыл про еще одно наказание - урожай. Сначала пытаешься вырастить, потом придумать - как его сохранить))) Сутками катать помидоры-огурцы, кабаки сок.... Брр
После переезда понял, что свободное время можно проводить поинтереснее. Поехать в парк, лес, горы, на экскурсию. Перекусить в кафешке чем-нибудь интересным. Сходить в Термы-спа. Вернуться отдохнувшим.
Поэтому продал этот вид "отдыха". Конечно, иногда ностальгия мучает, но в целом - без нее лучше.

Vladimir SEO #:
Почему прогу можно красть а картошку нет? И то и другое делал человек,  тратил силы время. 

капер Дмитрий этого искренне не понимает. У него все приводится к логике - "Зачем покупать, если можно своровать?" и борьбе с корпорациями.
Хотя вчера меня выбесил нетфликс, когда я заметил, что в базовую подписку теперь включен только HD контент.
За 4К будь добр, доплати еще пару долларов в месяц. Дмитро, помоги, выкачай последние релизы в 4К и пришли мне на флешке))) Ты же Робин Гут к тому же, должен помочь прозябающей еуропе)

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 раза. 
это все так, навскидку. Если повозиться, можно еще пооптимизировать. 

Всего: 7322