Last active
May 1, 2025 13:13
-
-
Save ve3xone/9d964754478fbf2dc6d5362d093f2211 to your computer and use it in GitHub Desktop.
Скрипт на питон который делает очень красивые скриншоты всего бранча с гитхаба, нужно это для проектного практикума чтоб на контрольных точках показывать прогресс по коммитам из private репозиториев
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import asyncio | |
| import glob | |
| from PIL import Image | |
| from urllib.parse import urlparse | |
| from pathlib import Path | |
| from playwright.async_api import async_playwright | |
| TAMPERMONKEY_SCRIPT = """ | |
| // ==UserScript== | |
| // @name GitHub Commits Cleaner | |
| // @namespace http://tampermonkey.net/ | |
| // @version 1.2 | |
| // @description Удаляет лишние элементы со страниц коммитов | |
| // @author ve3xone | |
| // @match https://github.com/*/*/commits/* | |
| // @grant none | |
| // ==/UserScript== | |
| (function () { | |
| 'use strict'; | |
| const baseSelectors = [ | |
| '.AppHeader-localBar', | |
| 'button[aria-label="Open global navigation menu"]', | |
| '.AppHeader-globalBar-end', | |
| '.d-flex.flex-column.flex-sm-row.gap-2', | |
| '.text-center', | |
| 'footer.footer.pt-8.pb-6.f6.color-fg-muted.p-responsive[role="contentinfo"]', | |
| 'svg.octicon-three-bars' | |
| ]; | |
| const extraSelectorsIfAfterParam = [ | |
| '.mb-3.prc-Stack-Stack-WJVsK', | |
| 'header.Box-sc-g0xbh4-0.fDhSWy.prc-PageLayout-Header-mQXK1', | |
| '.position-relative.header-wrapper.js-header-wrapper' | |
| ]; | |
| function removeElement(selector) { | |
| const el = document.querySelector(selector); | |
| if (el) el.remove(); | |
| } | |
| function removeAllElements(selectors) { | |
| selectors.forEach(selector => removeElement(selector)); | |
| } | |
| const urlHasAfterParam = window.location.search.includes('after='); | |
| const allSelectors = urlHasAfterParam | |
| ? baseSelectors.concat(extraSelectorsIfAfterParam) | |
| : baseSelectors; | |
| window.addEventListener('load', () => { | |
| removeAllElements(allSelectors); | |
| }); | |
| const observer = new MutationObserver(() => { | |
| removeAllElements(allSelectors); | |
| }); | |
| observer.observe(document.body, { | |
| childList: true, | |
| subtree: true | |
| }); | |
| })(); | |
| """ | |
| def images_to_pdf(prefix): | |
| images = sorted(glob.glob(f"commits_page_{prefix}_*.png")) | |
| if not images: | |
| print(f"❌ Нет изображений для {prefix}") | |
| return | |
| image_list = [Image.open(img).convert("RGB") for img in images] | |
| pdf_filename = f"{prefix}.pdf" | |
| image_list[0].save(pdf_filename, save_all=True, append_images=image_list[1:]) | |
| print(f"📄 PDF сохранён: {pdf_filename}") | |
| for img in images: | |
| Path(img).unlink() | |
| async def main(url, name_repo): | |
| async with async_playwright() as p: | |
| browser = await p.chromium.launch(headless=False) | |
| context = await browser.new_context( | |
| viewport={'width': 1280, 'height': 1280}, | |
| device_scale_factor=1.0 | |
| is_mobile=False, | |
| storage_state="github_state.json" | |
| ) | |
| page = await context.new_page() | |
| await page.add_init_script(TAMPERMONKEY_SCRIPT) | |
| page_num = 1 | |
| while True: | |
| print(f"🔄 Переход на страницу {page_num}: {url}") | |
| await page.goto(url) | |
| # await page.wait_for_load_state("networkidle") | |
| await page.wait_for_timeout(5000) # ждём очистки DOM | |
| # input() | |
| # Запоминаем ссылку на "next" | |
| try: | |
| next_link = await page.eval_on_selector( | |
| '[data-testid="pagination-next-button"]', | |
| 'el => el?.getAttribute("href")' | |
| ) | |
| # Удаляем блок пагинации, чтобы не мешал скриншоту | |
| await page.evaluate(""" | |
| const el = document.querySelector("div.d-flex.flex-justify-center.mt-2"); | |
| if (el) el.remove(); | |
| """) | |
| except: | |
| next_link = None | |
| if await page.locator("text=No commits history").is_visible(): | |
| print("⚠️ Нет истории коммитов. Выход.") | |
| break | |
| # Делаем скриншот | |
| filename = f"commits_page_{name_repo}_{page_num:02}.png" | |
| await page.screenshot(path=filename, full_page=True) | |
| print(f"📸 Скриншот сохранён: {filename}") | |
| # Если нет ссылки на следующую страницу — выход | |
| if not next_link: | |
| print("✅ Больше нет кнопки Next. Завершаем.") | |
| break | |
| # Обновляем URL | |
| url = "https://github.com" + next_link | |
| page_num += 1 | |
| await browser.close() | |
| links = [ | |
| 'https://github.com/it-professions-ru/client_DMK-dev/commits/master/', | |
| 'https://github.com/it-professions-ru/HH_model-dev/commits/master/', | |
| 'https://github.com/it-professions-ru/HH_model-dev/commits/dev', | |
| 'https://github.com/it-professions-ru/HH_model-dev/commits/deep_network', | |
| 'https://github.com/it-professions-ru/analytics-worker/commits/main/', | |
| 'https://github.com/it-professions-ru/Analytics_ClickHouse-dev/commits/main/', | |
| 'https://github.com/it-professions-ru/configs/commits/main/', | |
| 'https://github.com/it-professions-ru/data-miner-dev/commits/main/', | |
| 'https://github.com/it-professions-ru/dmk.ai-info.ru-dev/commits/main/', | |
| 'https://github.com/it-professions-ru/automated_analytics-dev/commits/main/', | |
| 'https://github.com/it-professions-ru/data-miner-old/commits/main/' | |
| ] | |
| for link in links: | |
| parts = urlparse(link).path.strip("/").split("/") | |
| repo = parts[1] | |
| branch = parts[3] | |
| prefix = f"it-professions-ru_{repo}_{branch}" | |
| asyncio.run(main(link, prefix)) | |
| images_to_pdf(prefix) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import asyncio | |
| from playwright.async_api import async_playwright | |
| async def save_github_login(): | |
| async with async_playwright() as p: | |
| browser = await p.chromium.launch(headless=False) | |
| context = await browser.new_context() | |
| page = await context.new_page() | |
| await page.goto("https://github.com/login") | |
| print("🔑 Войди в GitHub вручную в открывшемся окне...") | |
| # Ждём, пока пользователь не войдёт | |
| await page.wait_for_url("https://github.com/**", timeout=120000) | |
| await page.wait_for_timeout(120000) | |
| # Сохраняем куки/локалстораж | |
| await context.storage_state(path="github_state.json") | |
| print("✅ Сессия сохранена.") | |
| await browser.close() | |
| asyncio.run(save_github_login()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment