반응형
반응형

pip install wifi-qrcode-generator

 

Python을 사용하여 Wi-Fi QR 코드를 생성하려면 qrcodePillow 라이브러리를 활용할 수 있습니다. Wi-Fi QR 코드의 데이터 형식은 다음과 같습니다:

 

import qrcode
from PIL import Image

def generate_wifi_qrcode(ssid, password, encryption="WPA", hidden=False, output_file="wifi_qrcode.png"):
    """
    Generates a Wi-Fi QR code and saves it as an image.
    
    :param ssid: The Wi-Fi network name (SSID)
    :param password: The Wi-Fi password
    :param encryption: Encryption type ('WPA', 'WEP', or 'nopass')
    :param hidden: Whether the network is hidden (True/False)
    :param output_file: Name of the output image file
    """
    # Format Wi-Fi QR code data
    wifi_data = f"WIFI:S:{ssid};T:{encryption};P:{password};H:{'true' if hidden else 'false'};;"
    
    # Generate QR code
    qr = qrcode.QRCode(
        version=1,
        error_correction=qrcode.constants.ERROR_CORRECT_L,
        box_size=10,
        border=4,
    )
    qr.add_data(wifi_data)
    qr.make(fit=True)

    # Create and save the QR code image
    img = qr.make_image(fill_color="black", back_color="white")
    img.save(output_file)
    print(f"Wi-Fi QR code saved as {output_file}")

    # Open and show the image
    img.show()

# Example usage
generate_wifi_qrcode(
    ssid="MyWiFiNetwork",
    password="MySecurePassword",
    encryption="WPA",  # WPA/WEP/nopass
    hidden=False,       # Hidden network? True/False
    output_file="wifi_qrcode.png"
)

코드 설명

  1. Wi-Fi QR 코드 형식:
    • WIFI:S:<SSID>;T:<WPA/WEP/nopass>;P:<Password>;H:<Hidden (true/false)>;;
      • S: Wi-Fi 이름 (SSID)
      • T: 암호화 방식 (WPA, WEP, nopass)
      • P: 비밀번호
      • H: 네트워크 숨김 여부 (true 또는 false)
  2. QR 코드 생성:
    • **qrcode.QRCode**를 사용하여 데이터를 추가하고 이미지를 생성.
    • QR 코드는 기본적으로 검은색 fill_color와 흰색 back_color를 사용하여 생성.
  3. 결과 저장 및 표시:
    • 생성된 QR 코드를 wifi_qrcode.png로 저장.
    • **img.show()**를 사용하여 시스템 기본 이미지 뷰어에서 표시.

결과

  • wifi_qrcode.png 파일이 생성됩니다.
  • QR 코드를 스캔하면 자동으로 Wi-Fi 네트워크에 연결할 수 있습니다.

 

 


 

wifi_qrcode_generator

Generate a QR code for your WiFi network to let others quickly connect without needing to tell them your long and complicated password.

Installation

$ pip install wifi-qrcode-generator

Usage

CLI interactive mode

$ wifi-qrcode-generator

 

CLI non-interactive mode

$ wifi-qrcode-generator -s "Home WiFi" -p "very complicated password" -a WPA -o qr.png -P

Python API

#!/usr/bin/env python3
import wifi_qrcode_generator.generator

qr_code = wifi_qrcode_generator.generator.wifi_qrcode(
    ssid='Home WiFi', hidden=False, authentication_type='WPA', password='very complicated password'
)
qr_code.print_ascii()
qr_code.make_image().save('qr.png')

Dependencies

  • Pillow
  • qrcode

    wifi_qrcode_generator

    Generate a QR code for your WiFi network to let others quickly connect without needing to tell them your long and complicated password.
    $ pip install wifi-qrcode-generator
    
    Usage
    $ wifi-qrcode-generator
    
     Dependencies
    • Pillow
    • qrcode

      wifi_qrcode_generator

      Generate a QR code for your WiFi network to let others quickly connect without needing to tell them your long and complicated password.
      $ pip install wifi-qrcode-generator
      
      Usage
      $ wifi-qrcode-generator
      
       Dependencies
    • #!/usr/bin/env python3 import wifi_qrcode_generator.generator qr_code = wifi_qrcode_generator.generator.wifi_qrcode( ssid='Home WiFi', hidden=False, authentication_type='WPA', password='very complicated password' ) qr_code.print_ascii() qr_code.make_image().save('qr.png')
    • Python API
    • $ wifi-qrcode-generator -s "Home WiFi" -p "very complicated password" -a WPA -o qr.png -P
    • CLI non-interactive mode
    • CLI interactive mode
    • Installation
  • #!/usr/bin/env python3 import wifi_qrcode_generator.generator qr_code = wifi_qrcode_generator.generator.wifi_qrcode( ssid='Home WiFi', hidden=False, authentication_type='WPA', password='very complicated password' ) qr_code.print_ascii() qr_code.make_image().save('qr.png')
  • Python API
  • $ wifi-qrcode-generator -s "Home WiFi" -p "very complicated password" -a WPA -o qr.png -P
  • CLI non-interactive mode
  • CLI interactive mode
  • Installation

 

https://pypi.org/project/wifi-qrcode-generator/

 

wifi-qrcode-generator

Generate a QR code for your WiFi network to let others quickly connect.

pypi.org

 

반응형
반응형

Sunburst Chart

 

Sunburst Chart는 계층적 데이터를 시각화하는 데 사용되는 원형 차트입니다.

데이터의 루트는 중앙에 있고, 계층적으로 데이터를 표현하며, 내부에서 외부로 확장됩니다.

각 섹션은 데이터를 크기별로 구분하여 보여줍니다.

 

"""
    Sunburst Chart는 계층적 데이터를 시각화하는 데 사용되는 원형 차트입니다. 
    데이터의 루트는 중앙에 있고, 
    계층적으로 데이터를 표현하며, 내부에서 외부로 확장됩니다. 
    각 섹션은 데이터를 크기별로 구분하여 보여줍니다.
"""

import plotly.express as px
from PIL import Image

# 계층적 데이터 정의
data = dict(
    labels=["Root", "Child 1", "Child 2", "Grandchild 1", "Grandchild 2", "Grandchild 3"],
    parents=["", "Root", "Root", "Child 1", "Child 1", "Child 2"],
    values=[10, 5, 5, 2, 3, 5]
)

# Sunburst Chart 생성
fig = px.sunburst(
    data,
    names='labels',
    parents='parents',
    values='values',
    title="Sunburst Chart Example"
)

# fig.show()

# Sunburst Chart를 이미지로 저장
image_path = "sunburst_chart_001.png"
fig.write_image(image_path, width=800, height=600)
print(f"Sunburst chart saved as '{image_path}'")

# 저장된 이미지 출력
image = Image.open(image_path)
image.show()  # 기본 이미지 뷰어로 열기

 

 

 

반응형
반응형

What’s New in Python 3.13

https://medium.com/@rdhankhar899/whats-new-in-python-3-13-45516e6568a8

 

What’s New in Python 3.13

This article explains the new features in Python 3.13, compared to 3.12. Python 3.13 was released on October 7, 2024, marking a significant…

medium.com

https://docs.python.org/ko/3.13/whatsnew/3.13.html#what-s-new-in-python-3-13

 

What’s New In Python 3.13

Editors, Adam Turner and Thomas Wouters,. This article explains the new features in Python 3.13, compared to 3.12. Python 3.13 was released on October 7, 2024. For full details, see the changelog. ...

docs.python.org

This article explains the new features in Python 3.13, compared to 3.12. Python 3.13 was released on October 7, 2024, marking a significant advancement for the language. Many of the most impactful changes occur behind the scenes, so they may take time to notice.

Python 3.13 is setting the stage for future enhancements, particularly in terms of performance improvements. For full details, see the changelog.

Python 3.13 is the latest stable release of the Python programming language, with a mix of changes to the language, the implementation and the standard library. The biggest changes include a new interactive interpreter, experimental support for running in a free-threaded mode (PEP 703), and a Just-In-Time compiler (PEP 744).

Error messages continue to improve, with tracebacks now highlighted in color by default. The locals() builtin now has defined semantics for changing returning mapping, and type parameters now support values.

The library changes contain removal of deprecated APIs and modules, as well as the usual improvements in user-friendliness and correctness. Several legacy standard library modules have now been removed following their deprecation in Python 3.11 (PEP 594).

Here is a list of major features and improved modules.

· Improved REPL

· Free Threading Cpython

· An Experimental just-in-time (JIT)

· Improved Error Messages

· Copy’s Replace

· Support for Mobile Platforms

Improved REPL

Python now uses a new interactive shell by default, based on code from the PyPy project. When the user starts the REPL from an interactive terminal, the following new features are now supported:

  • Multiline editing with history preservation.
  • Direct support for REPL-specific commands like help, exit, and quit, without the need to call them as functions.
  • Prompts and tracebacks with color enabled by default.
  • Interactive help browsing using F1 with a separate command history.
  • History browsing using F2 that skips output as well as the >>> and  prompts.
  • “Paste mode” with F3 that makes pasting larger blocks of code easier (press F3 again to return to the regular prompt).

Free Threading Cpython

CPython now has experimental support for running in a free-threaded mode, with the global interpreter lock (GIL) disabled. This is an experimental feature and therefore is not enabled by default. The free-threaded mode requires a different executable, usually called python3.13t or python3.13t.exe. Pre-built binaries marked as free-threaded can be installed as part of the official Windows and macOS installers, or CPython can be built from source with the — disable-gil option.

An Experimental just-in-time (JIT)

When CPython is configured and built using the — enable-experimental-jit option, a just-in-time (JIT) compiler is added which may speed up some Python programs. On Windows, use PCbuild/build.bat — experimental-jit to enable the JIT or — experimental-jit-interpreter to enable the Tier 2 interpreter. Build requirements and further supporting information are contained at Tools/jit/README.md.

Improved Error Messages

The interpreter now uses color by default when displaying tracebacks in the terminal. This feature can be controlled via the new PYTHON_COLORS environment variable as well as the canonical NO_COLOR and FORCE_COLOR environment variables. (Contributed by Pablo Galindo Salgado in gh-112730.)

The error message now tries to suggest the correct keyword argument when an incorrect keyword argument is passed to a function.

# Incorrect usage of the built-in sorted() function
sorted([3, 1, 2], reversed=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    sorted([3, 1, 2], reversed=True)
    ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
TypeError: sorted() got an unexpected keyword argument 'reversed'. Did you mean 'reverse'?

Copy’s Replace

The new replace() function and the replace protocol make creating modified copies of objects much simpler. This is especially useful when working with immutable objects. The following types support the replace() function and implement the replace protocol:

Any user-defined class can also support copy.replace() by defining the __replace__() method. (Contributed by Serhiy Storchaka in gh-108751.)

Support for Mobile Platforms

PEP 730: iOS is now a PEP 11 supported platform, with the arm64-apple-ios and arm64-apple-ios-simulator targets at tier 3 (iPhone and iPad devices released after 2013 and the Xcode iOS simulator running on Apple silicon hardware, respectively). x86_64-apple-ios-simulator (the Xcode iOS simulator running on older x86_64 hardware) is not a tier 3 supported platform, but will have best-effort support. (PEP written and implementation contributed by Russell Keith-Magee in gh-114099.)

PEP 738: Android is now a PEP 11 supported platform, with the aarch64-linux-android and x86_64-linux-android targets at tier 3. The 32-bit targets arm-linux-androideabi and i686-linux-android are not tier 3 supported platforms, but will have best-effort support. (PEP written and implementation contributed by Malcolm Smith in gh-116622.)

반응형
반응형

PyQt5와 requests 및 BeautifulSoup를 이용해 URL을 입력하고, 해당 웹 페이지의 내용을 크롤링하여 보여주는 기본 프로그램.

입력한 URL의 HTML 내용과 크롤링된 특정 텍스트 내용을 보여주는 두 개의 영역

import sys
import requests
from bs4 import BeautifulSoup
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QLineEdit, QPushButton, QScrollArea, QTextBrowser, QTextEdit
from PyQt5.QtCore import Qt

class WebCrawlerApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # 창 설정
        self.setWindowTitle("URL Web Crawler")
        self.setGeometry(300, 300, 800, 600)
        
        # 메인 레이아웃 설정
        layout = QVBoxLayout()

        # URL 입력창 및 버튼 추가
        self.url_input = QLineEdit(self)
        self.url_input.setPlaceholderText("Enter URL here...")
        layout.addWidget(self.url_input)
        
        self.submit_button = QPushButton("Submit", self)
        self.submit_button.clicked.connect(self.fetch_web_content)
        layout.addWidget(self.submit_button)
        
        # HTML 내용 표시 (링크 지원을 위해 QTextBrowser 사용)
        self.html_label = QLabel("Page HTML Content:")
        layout.addWidget(self.html_label)
        
        self.html_content = QTextBrowser(self)
        self.html_content.setOpenExternalLinks(False)  # QTextBrowser 내부에서 링크 클릭 이벤트를 처리
        self.html_content.anchorClicked.connect(self.handle_link_click)
        html_scroll = QScrollArea(self)
        html_scroll.setWidgetResizable(True)
        html_scroll.setWidget(self.html_content)
        layout.addWidget(html_scroll)

        # 크롤링된 내용을 보여줄 텍스트 창
        self.crawl_label = QLabel("Crawled Data:")
        layout.addWidget(self.crawl_label)
        
        self.crawled_content = QTextEdit(self)
        self.crawled_content.setReadOnly(True)
        crawl_scroll = QScrollArea(self)
        crawl_scroll.setWidgetResizable(True)
        crawl_scroll.setWidget(self.crawled_content)
        layout.addWidget(crawl_scroll)
        
        # 레이아웃 설정
        self.setLayout(layout)

    def fetch_web_content(self):
        # URL 가져오기
        url = self.url_input.text().strip()
        if not url:
            self.html_content.setText("Please enter a valid URL.")
            return
        
        try:
            # 웹 페이지 요청 및 파싱
            response = requests.get(url)
            response.raise_for_status()
            html_text = response.text
            
            # HTML 내용을 보여줌
            self.html_content.setHtml(html_text)
            
            # BeautifulSoup으로 HTML 파싱
            soup = BeautifulSoup(html_text, 'html.parser')
            
            # 특정 태그 내용 크롤링 예시 (모든 <p> 태그 내용)
            paragraphs = soup.find_all('p')
            crawled_data = "\n\n".join([p.get_text(strip=True) for p in paragraphs])
            
            # 크롤링된 내용 표시
            if crawled_data:
                self.crawled_content.setText(crawled_data)
            else:
                self.crawled_content.setText("No <p> tags found on the page.")

        except requests.exceptions.RequestException as e:
            self.html_content.setText(f"Error fetching the URL: {e}")
            self.crawled_content.setText("")

    def handle_link_click(self, url):
        # 링크를 클릭하면 URL 입력창에 설정하고 자동으로 Submit
        self.url_input.setText(url.toString())
        self.fetch_web_content()

# 애플리케이션 실행
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = WebCrawlerApp()
    window.show()
    sys.exit(app.exec_())
반응형
반응형

 

입력받은 url을 다운로드 받고, MP3로 변환하고 싶으면 변환버튼.

다운 받은 파일 리스트 페이지 에서 파일 더블 클릭시 실행.

 

 

 

 

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QLineEdit, QScrollArea, QMessageBox
import yt_dlp
import threading
from moviepy.editor import AudioFileClip
 

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # 윈도우 설정
        self.setWindowTitle("YouTube Downloader & MP4 to MP3 Converter")
        self.setGeometry(300, 300, 600, 400)

        # 메인 레이아웃 설정
        self.main_layout = QVBoxLayout()

        # 버튼 레이아웃 (좌에서 우로 배치)
        button_layout = QHBoxLayout()

        # 버튼 1: YouTube URL 다운로드 버튼
        self.youtube_button = QPushButton("Download YouTube Video", self)
        self.youtube_button.clicked.connect(self.show_youtube_download_form)
        button_layout.addWidget(self.youtube_button)

        # 버튼 2: MP4 to MP3 변환 버튼
        self.convert_button = QPushButton("Convert MP4 to MP3", self)
        self.convert_button.clicked.connect(self.confirm_convert_form)  # 확인 창 함수 연결
        button_layout.addWidget(self.convert_button) 

        # 버튼 3: Downloads 폴더의 파일 리스트 보기 버튼
        self.show_files_button = QPushButton("Show Downloaded Files", self)
        self.show_files_button.clicked.connect(self.show_downloaded_files)
        button_layout.addWidget(self.show_files_button)

        # 버튼 레이아웃 추가
        self.main_layout.addLayout(button_layout)

        # YouTube URL 입력 필드 (초기에는 숨김)
        self.url_input = QLineEdit(self)
        self.url_input.setPlaceholderText("Enter YouTube URL here...")
        self.url_input.setVisible(False)  # 초기에는 숨김
        self.main_layout.addWidget(self.url_input)

        # 상태 및 결과 표시 레이블 (스크롤 가능)
        self.result_label = QLabel(self)
        self.result_label.setWordWrap(True)
        
        scroll_area = QScrollArea(self)
        scroll_area.setWidgetResizable(True)
        scroll_area.setWidget(self.result_label)
        self.main_layout.addWidget(scroll_area)

        # 메인 레이아웃 설정
        self.setLayout(self.main_layout)

    def show_youtube_download_form(self):
        # 입력 필드가 이미 있는지 확인 후 없을 때만 추가
        # 입력 필드를 보이도록 설정하고, 플레이스홀더 텍스트 설정
        self.url_input.setVisible(True)
        self.url_input.setPlaceholderText("Enter YouTube URL here...")
        self.url_input.clear()  # 이전 입력값 지우기
        self.result_label.setText("Enter a YouTube URL to download:") 

    def download_video(self):
        url = self.url_input.text().strip()
        if url:
            self.result_label.setText("Downloading... Please wait.")
            threading.Thread(target=self.youtube_download_process, args=(url,)).start()
        else:
            self.result_label.setText("Please enter a valid YouTube URL.")

    def youtube_download_process(self, url):
        ydl_opts = {
            'format': 'best',
            'outtmpl': './downloads/%(title)s.%(ext)s',
            'progress_hooks': [self.progress_hook]
        }
        with yt_dlp.YoutubeDL(ydl_opts) as ydl:
            ydl.download([url])

    def progress_hook(self, d):
        if d['status'] == 'downloading':
            percent = d['_percent_str']
            speed = d.get('speed', 'Unknown')
            eta = d.get('eta', 'Unknown')
            self.result_label.setText(f"Downloading: {percent} - Speed: {speed} - ETA: {eta}s")
        elif d['status'] == 'finished':
            self.result_label.setText(f"Download complete!")

    def confirm_convert_form(self):
        # 확인/취소 메시지 박스를 생성
        reply = QMessageBox.question(self, 'Convert MP4 to MP3',
                                     "Are you sure you want to convert all MP4 files in the folder to MP3?",
                                     QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

        # 사용자가 Yes를 선택한 경우에만 변환 함수 실행
        if reply == QMessageBox.Yes:
            self.show_convert_form()

    def show_convert_form(self):
        # URL 입력창 숨김
        self.url_input.setVisible(False)
        
        # MP4 파일 선택 및 MP3로 변환 메시지 설정
        self.result_label.setText("Converting all MP4 files in the folder to MP3...")
        threading.Thread(target=self.convert_mp4_to_mp3).start()

    def convert_mp4_to_mp3(self):
        folder_path = './downloads'  # MP4 파일이 있는 폴더
         

        for filename in os.listdir(folder_path):
            if filename.endswith(".mp4"):
                mp4_path = os.path.join(folder_path, filename)
                mp3_path = os.path.join(folder_path, f"{os.path.splitext(filename)[0]}.mp3")
                
                if os.path.exists(mp3_path):
                    self.result_label.setText(self.result_label.text() + f"\nSkipping {filename}: MP3 already exists.")
                    continue

                audio_clip = AudioFileClip(mp4_path)
                audio_clip.write_audiofile(mp3_path)
                audio_clip.close()
                self.result_label.setText(self.result_label.text() + f"\nConverted: {filename} to MP3.")

        self.result_label.setText(self.result_label.text() + "\nAll MP4 files converted to MP3.")

    def show_downloaded_files(self):
        # URL 입력창 숨김
        self.url_input.setVisible(False)
        
        # ./downloads 폴더의 파일 리스트를 표시
        folder_path = './downloads'
        if not os.path.exists(folder_path):
            self.result_label.setText("No files found. The downloads folder does not exist.")
            return

        files = os.listdir(folder_path)
        if files:
            file_list = "\n".join(files)
            self.result_label.setText(f"Files in {folder_path}:\n{file_list}")
        else:
            self.result_label.setText("No files found in the downloads folder.")



# PyQt 애플리케이션 실행
if __name__ == "__main__":
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())
반응형
반응형

[python]  폴더 안의 모든 mp4 파일을 mp3로 변환하기

 

 

import os
from pathlib import Path
 

from moviepy.editor import *

# MP4 파일이 있는 폴더 경로 지정
folder_path = './downloads'

import file_rename_underbar as fru

# 폴더내의 파일명 rename
fru.replace_spaces_in_filenames(folder_path)


# 폴더 내의 모든 파일 확인
for filename in os.listdir(folder_path):
    if filename.endswith('.mp4'):
        mp4_path = os.path.join(folder_path, filename)
        mp3_path = os.path.join(folder_path, filename.replace('.mp4', '.mp3'))
        
        # 비디오에서 오디오 추출 후 MP3로 저장
        video = VideoFileClip(mp4_path)
        video.audio.write_audiofile(mp3_path)
        video.close()  # 명시적으로 close 호출하여 자원 해제

        print(f"Converted: {filename} to MP3")
    else:
        print(f"Converted Not: {filename} to MP3")

 

 

 

 

반응형

+ Recent posts