Created
June 17, 2020 09:55
-
-
Save tamamu/00b8ac7dc3644f46c734101d61256cda to your computer and use it in GitHub Desktop.
Super Simplified Web Browser
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 tkinter as tk | |
import urllib.request | |
import io | |
from PIL import Image, ImageTk | |
from urllib.parse import urljoin | |
from html.parser import HTMLParser | |
from tkx import VerticalScrolledFrame | |
class MyHTMLParser(HTMLParser): | |
def __init__(self, parent): | |
super().__init__() | |
self.cur_tag = None | |
self.cur_attrs = None | |
self.cur_url = "" | |
self.parent = parent | |
def handle_starttag(self, tag, attrs): | |
self.cur_tag = tag | |
self.cur_attrs = {attr[0]:attr[1] for attr in attrs} | |
if self.cur_tag == 'img': | |
src = self.cur_attrs['src'] | |
if src != "http": | |
src = urljoin(self.cur_url, src) | |
with urllib.request.urlopen(src) as f: | |
pilimg = Image.open(io.BytesIO(f.read())) | |
img = ImageTk.PhotoImage(pilimg) | |
self.parent.add_image(img) | |
return | |
def handle_data(self, data): | |
if self.cur_tag == "a": | |
href = self.cur_attrs['href'] | |
if href != "http": | |
href = urljoin(self.cur_url, href) | |
self.parent.add_link(data, href) | |
return | |
if self.cur_tag not in ['script', 'style'] and data.strip() != "": | |
self.parent.add_text(data) | |
class Application(tk.Frame): | |
def __init__(self, master=None): | |
super().__init__(master) | |
self.parser = MyHTMLParser(self) | |
self.master = master | |
self.cache = [] | |
self.pack(expand=1, fill=tk.BOTH, anchor=tk.NW) | |
self.create_widgets() | |
def create_widgets(self): | |
# URL入力バー | |
self.url_bar = tk.Entry(self) | |
self.url_bar.grid(column = 0, row = 0, sticky = 'nsew') | |
self.url_bar.insert(tk.END, 'https://www.google.com/') | |
# 移動ボタン | |
self.url_button = tk.Button(self, text="GO", command=self.enter_url, fg='RED') | |
self.url_button.grid(column = 1, row = 0, sticky = 'nsew') | |
self.columnconfigure(0, weight=1) | |
# ページフレーム | |
self.page = VerticalScrolledFrame(self, bg='WHITE') | |
self.page.grid(column = 0, row = 1, columnspan= 2, sticky = 'nsew') | |
self.rowconfigure(1, weight=1) | |
def reset_page(self): | |
for widget in self.page.interior.winfo_children(): | |
widget.pack_forget() | |
def enter_url(self): | |
#ページをリセット | |
self.reset_page() | |
# URLを取得 | |
url = self.url_bar.get() | |
self.parser.cur_url = url | |
# GETリクエスト | |
with urllib.request.urlopen(url) as f: | |
data = f.read().decode('utf-8') | |
self.parser.feed(data) | |
def add_text(self, data): | |
x1 = tk.Label(self.page.interior, text=data, bg='WHITE') | |
x1.pack() | |
def add_link(self, data, href): | |
x1 = tk.Button(self.page.interior, text=data, bg='WHITE', | |
command=lambda:( | |
self.url_bar.delete(0, tk.END), | |
self.url_bar.insert(tk.END, href), | |
self.enter_url(), | |
) | |
) | |
x1.pack() | |
def add_image(self, img): | |
self.cache.append(img) | |
x1 = tk.Label(self.page.interior, image=img) | |
x1.pack() | |
root = tk.Tk() | |
root.geometry('800x600') | |
app = Application(master=root) | |
app.mainloop() |
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
from tkinter import * | |
class VerticalScrolledFrame(Frame): | |
"""A pure Tkinter scrollable frame that actually works! | |
* Use the 'interior' attribute to place widgets inside the scrollable frame | |
* Construct and pack/place/grid normally | |
* This frame only allows vertical scrolling | |
""" | |
def __init__(self, parent, *args, **kw): | |
Frame.__init__(self, parent, *args, **kw) | |
# スクロールバーの作成 | |
vscrollbar = Scrollbar(self, orient=VERTICAL) | |
vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE) | |
canvas = Canvas(self, bd=0, highlightthickness=0, | |
yscrollcommand=vscrollbar.set, bg='WHITE') | |
canvas.pack(side=LEFT, fill=BOTH, expand=TRUE) | |
vscrollbar.config(command=canvas.yview) | |
# ビューをリセット | |
canvas.xview_moveto(0) | |
canvas.yview_moveto(0) | |
# create a frame inside the canvas which will be scrolled with it | |
self.interior = interior = Frame(canvas, bg='WHITE') | |
interior_id = canvas.create_window(0, 0, window=interior, | |
anchor=NW) | |
# track changes to the canvas and frame width and sync them, | |
# also updating the scrollbar | |
def _configure_interior(event): | |
# update the scrollbars to match the size of the inner frame | |
size = (interior.winfo_reqwidth(), interior.winfo_reqheight()) | |
canvas.config(scrollregion="0 0 %s %s" % size) | |
if interior.winfo_reqwidth() != canvas.winfo_width(): | |
# update the canvas's width to fit the inner frame | |
canvas.config(width=interior.winfo_reqwidth()) | |
interior.bind('<Configure>', _configure_interior) | |
def _configure_canvas(event): | |
if interior.winfo_reqwidth() != canvas.winfo_width(): | |
# update the inner frame's width to fill the canvas | |
canvas.itemconfigure(interior_id, width=canvas.winfo_width()) | |
canvas.bind('<Configure>', _configure_canvas) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment