Je voulais un outil de type GUI qui ouvre des pages avec la même balise de recherche à la fois sur les sites EC et les sites de publication de travail.
・ (La classe json est une amélioration de celle précédemment créée et en a fait une partie commune) ・ Implémentation de la classe de gestion de la combo de Tkinter et en a fait une partie commune -Définissez l'interface graphique avec la méthode principale, lisez les données et ouvrez la page Web sélectionnée par l'interface graphique.
・ Windows10 ・ Python 3.7.0 ・ Le développement est Pycharm
L'interface graphique ressemble à ceci.

webSiteDetails.json
{
  "WebSiteA": {
    "OnlyOpenPage": true,
    "PageSet": [
      "http://foobar.com",
      "http://foobar.com",
      "http://foobar.com",
      "http://foobar.com",
      "http://foobar.com",
      "http://foobar.com",
      "http://foobar.com",
      "http://foobar.com",
      "http://foobar.com"
    ]
  },
  "WebSiteB": {
    "OnlyOpenPage": true,
    "PageSet": [
      "http://foobar.com",
      "http://foobar.com"
    ]
  },
  "WebSiteC": {
    "OnlyOpenPage": true,
    "PageSet": [
      "http://foobar.com",
      "http://foobar.com",
      "http://foobar.com",
      "http://foobar.com"
    ]
  },
  "WebSiteD": {
    "OnlyOpenPage": true,
    "PageSet": [
      "http://foobar.com",
      "http://foobar.com",
      "http://foobar.com",
      "http://foobar.com"
    ]
  },
  "WebSiteE": {
    "OnlyOpenPage": true,
    "PageSet": [
      "http://foobar.com",
      "http://foobar.com",
      "http://foobar.com"
    ]
  }
}
La propriété "Only OpenPage" a été ajoutée Lors de l'examen de la mise en œuvre de la fonction de grattage à l'avenir Ouvrez-le simplement Prime de traitement de grattage, Je voulais faire une distinction.
JsonHandler.py
import json
class JsonHandler:
    def __init__(self, jsonPath):
        #Lire le fichier json
        self.file = open(jsonPath, 'r', encoding="utf-8_sig")
        self.jsonData = json.load(self.file)
    #Obtenir les données JSON pour l'imbrication principale
    def getParam_OneNest(self, args):
        return self.jsonData[args]
    #Obtenir la liste des données JSON du nid principal
    def getAll_OneNest(self):
        # list = []
        # for d in self.jsonData.keys():
        #     list.append(d)
        list = [d for d in self.jsonData.keys()]
        return list
    #Obtenir des données JSON pour l'imbrication secondaire
    def getParam_TwoNest(self, args1, args2):
        return self.jsonData[args1][args2]
    def __del__(self):
        #Fermer le fichier
        self.file.close()
J'ai changé un peu celui que j'avais créé avant (*). Parce qu'il était nécessaire d'acquérir uniquement les données du nid principal à la fois. [※:https://qiita.com/dede-20191130/items/65b0f4c3c2b5c7f97546]
list = [d for d in self.jsonData.keys()]
Il s'agit d'un format d'inclusion de liste.
TkHandler_Combo_1.py
import tkinter as tk
import tkinter.ttk as ttk
class TkHandler_Combo_1:
    """Parties communes de l'interface graphique. Créer une zone de liste déroulante"""
    def __init__(self, rootTitle='Titre', rootGeometry='640x480'):
        #Créer un cadre racine
        self.root = tk.Tk()
        self.root.title(rootTitle)
        #Taille de la fenêtre racine comme valeur d'argument
        self.root.geometry(rootGeometry)
        #Fermer le paramètre d'événement
        self.root.protocol("WM_DELETE_WINDOW", self.onClosing)
        self.frame = None
        self.label = None
        self.combo = None
        self.button = None
        self.isDestroyed = False
    def createFrame(self):
        #Créer un cadre
        self.frame = ttk.Frame(self.root, width=self.root.winfo_width() - 20, height=self.root.winfo_height() - 20,
                               padding=10)
        self.frame.pack()
    def createLabel(self, myText="Veuillez sélectionner"):
        #Créer une étiquette
        self.label = ttk.Label(self.frame, text=myText, padding=(5, 5))
        self.label.pack()
    def createCombo(self, myWidth=None, myState='readonly', myValue=None, ):
        #réglage de la largeur
        myWidth = myWidth or self.frame.winfo_width() - 20
        #Créer une zone de liste déroulante
        self.combo = ttk.Combobox(self.frame, width=myWidth, state=myState)
        self.combo["values"] = myValue
        #Valeur par défaut(index=0)Mis à
        self.combo.current(0)
        #Placement de la liste déroulante
        self.combo.pack(padx=5, pady=5, fill=tk.X)
    def createButton(self, myText="Courir", myFunc=None):
        """Prenez une fonction comme argument"""
        #Paramètres de fonction
        myFunc = myFunc or (lambda: self.dummy())
        #Créer un bouton
        self.button = tk.Button(text=myText, command=lambda: myFunc(self.combo.get()))
        #* ↑↑ Au début, c'était implémenté comme ça
        # if myFunc:
        #     self.button = tk.Button(text=myText, command=lambda: myFunc(self.combo.get()))
        # else:
        #     self.button = tk.Button(text=myText, command=lambda: self.dummy())
        #Placement des boutons
        self.button.pack(padx=5, pady=5, )
    def dummy(self, arg=''):
        pass
    def mainLoop(self):
        self.root.mainloop()
    def onClosing(self):
        self.root.destroy()
        self.isDestroyed = True
    def __del__(self):
        if not self.isDestroyed:
            self.root.destroy()
#Fermer les paramètres de l'événement
        self.root.protocol("WM_DELETE_WINDOW", self.onClosing)
Une syntaxe qui définit une méthode appelée lorsque la fenêtre est fermée sans appuyer sur le bouton d'exécution. Effacez le cadre avant de fermer avec onClosing Empêche les erreurs lorsque le destructeur (fonction \ __ del__) fonctionne.
    def createCombo(self, myWidth=None, myState='readonly', myValue=None, ):
        #réglage de la largeur
        myWidth = myWidth or self.frame.winfo_width() - 20
Si un argument est spécifié pour myWidth, il continuera à avoir cette valeur, Si l'argument par défaut Aucun est laissé, une valeur 20 plus petite que la valeur de largeur du cadre sera entrée.
Je me suis référé à cet article pour savoir comment utiliser ou. https://blog.pyq.jp/entry/python_kaiketsu_181016
La raison pour laquelle je n'ai pas mis "self.frame.winfo_width () -20" directement dans l'argument par défaut est Il semble que vous ne pouvez pas prendre les membres de champ de votre propre classe comme arguments. Si quelqu'un sait qu'il existe un moyen possible, faites-le moi savoir.
    def createButton(self, myText="Courir", myFunc=None):
        """Prenez une fonction comme argument"""
        #Paramètres de fonction
        myFunc = myFunc or (lambda: self.dummy())
        #Créer un bouton
        self.button = tk.Button(text=myText, command=lambda: myFunc(self.combo.get()))
        #* ↑↑ Au début, c'était implémenté comme ça
        # if myFunc:
        #     self.button = tk.Button(text=myText, command=lambda: myFunc(self.combo.get()))
        # else:
        #     self.button = tk.Button(text=myText, command=lambda: self.dummy())
Objet bouton Tkinter comme événement lorsqu'il est pressé Une fonction est affectée à l'argument de commande.
Par conséquent, lorsque la méthode createButton est appelée Vous devez préparer une fonction côté appelant.
Cependant, en en faisant une partie commune, Je voulais préparer un argument par défaut au cas où la fonction ne serait pas spécifiée.
Au début, j'ai essayé cela.
def createButton(self, myText="Courir", myFunc=lambda: pass):
Cela n'a pas fonctionné. Il semble difficile de définir la fonction lambda comme argument.
Par conséquent, définissez une méthode factice factice dans la classe. J'ai essayé de le remplacer.
Ici, comme mentionné ci-dessus, "vous ne pouvez pas prendre le membre du champ que votre propre classe a comme argument", donc J'ai écrit comme suit.
    def createButton(self, myText="Courir", myFunc=None):
        """Prenez une fonction comme argument"""
        # if myFunc:
        #     self.button = tk.Button(text=myText, command=lambda: myFunc(self.combo.get()))
        # else:
        #     self.button = tk.Button(text=myText, command=lambda: self.dummy())
C'était bien, mais c'est un peu redondant Ecrire une expression qui définit le champ de bouton deux fois est deux fois plus difficile à gérer.
Par conséquent, il a été réécrit comme suit.
    def createButton(self, myText="Courir", myFunc=None):
        """Prenez une fonction comme argument"""
        #Paramètres de fonction
        myFunc = myFunc or (lambda: self.dummy())
        #Créer un bouton
        self.button = tk.Button(text=myText, command=lambda: myFunc(self.combo.get()))
QuickBrowsing.py
import os
import subprocess
import sys
#Réinitialiser le chemin de recherche du module
#Rendre possible de démarrer en double-cliquant
sys.path.append(os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH") + r"\PycharmProjects\CreateToolAndTest")
from Commons.JsonHandler import JsonHandler
from Commons.TkHandler_Combo_1 import TkHandler_Combo_1
import webbrowser
from time import sleep
# global
jsonHandler = None
siteList = None
tkHandler = None
siteName = None
def Main():
    global jsonHandler
    global siteList
    global tkHandler
    global siteName
    #Acquisition d'objets
    jsonHandler = JsonHandler(
        r'C:\Users\dede2\PycharmProjects\CreateToolAndTest\Tool_Python/QuickBrowsing/webSiteDetails.json')
    siteList = jsonHandler.getAll_OneNest()
    #Affichage du formulaire
    tkHandler = TkHandler_Combo_1('Navigation rapide', '640x200')
    tkHandler.createFrame()
    tkHandler.createLabel('Sélectionnez le site Web pour l'affichage par lots.')
    tkHandler.createCombo(myValue=siteList)
    tkHandler.createButton(myFunc=getSiteName)
    tkHandler.mainLoop()
    #Si le site n'est pas défini, il se termine normalement
    #Si la page Web n'est pas enregistrée, elle se termine normalement
    if siteName == None or not jsonHandler.getParam_TwoNest(siteName, 'OnlyOpenPage'):
        exit(0)
    #Ouvrez les sites Web dans l'ordre
    subprocess.Popen("start chrome /new-tab www.google.com --new-window", shell=True)
    sleep(1)
    browser = webbrowser.get(r'"' + os.getenv(r'ProgramFiles(x86)') + \
                             r'\Google\Chrome\Application\chrome.exe" %s')
    for url in jsonHandler.getParam_TwoNest(siteName, 'PageSet'):
        browser.open(url)
def getSiteName(argName=''):
    global tkHandler
    global siteName
    tkHandler.onClosing()
    siteName = argName
if __name__ == '__main__':
    Main()
siteList = jsonHandler.getAll_OneNest()
réduction
tkHandler.createCombo(myValue=siteList)
Obtenez uniquement l'en-tête du nom du site de json Faites-en un élément dans la liste déroulante.
tkHandler.createButton(myFunc=getSiteName)
réduction
def getSiteName(argName=''):
    global tkHandler
    global siteName
    tkHandler.onClosing()
    siteName = argName
Après avoir appuyé sur le bouton GUI, Je mets une valeur dans une variable globale et je la garde.
Après vérification, utilisez la méthode open_new du module Webbrowser. Il dit qu'il peut être ouvert dans une nouvelle fenêtre.
** Mais quand j'essaye de le déplacer, ça ne marche pas, ** ** S'ouvre comme un nouvel onglet dans la fenêtre d'origine. ** **
Apparemment, cela semble être une telle spécification. https://docs.python.org/ja/3/library/webbrowser.html
webbrowser.open_new(url) Si possible, ouvrez l'url dans une nouvelle fenêtre de votre navigateur par défaut, sinon ouvrez l'url dans une seule fenêtre de votre navigateur.
webbrowser.open_new_tab(url) Si possible, ouvrez l'url dans une nouvelle page ("onglet") dans le navigateur par défaut, sinon agissez comme open_new ().
Si chrome a été ouvert à l'origine, sous forme d'onglet de cette fenêtre Devrait ouvrir.
#Ouvrez les sites Web dans l'ordre
    subprocess.Popen("start chrome /new-tab www.google.com --new-window", shell=True)
    sleep(1)
    browser = webbrowser.get(r'"' + os.getenv(r'ProgramFiles(x86)') + \
                             r'\Google\Chrome\Application\chrome.exe" %s')
    for url in jsonHandler.getParam_TwoNest(siteName, 'PageSet'):
        browser.open(url)
Ouvrez le navigateur Chrome dans une nouvelle fenêtre avec le sous-processus. Après avoir attendu une seconde J'ai décidé d'ouvrir toutes les pages du site sélectionné dans cette fenêtre à la fois.
Il peut être possible de l'implémenter de manière plus élégante.
Les derniers outils et code source sont disponibles ici. ↓ https://github.com/dede-20191130/CreateToolAndTest/tree/master/Tool_Python/QuickBrowsing
Veuillez commenter si vous avez des suppléments.
Une case à cocher a été implémentée dans l'interface graphique pour empêcher l'outil de quitter même après avoir appuyé sur le bouton de processus.
La classe enfant suivante a été créée par héritage. (Puisque la méthode d'enregistrement de chameau pour les fonctions et les variables ne semble pas être la norme python Changé pour utiliser la méthode d'enregistrement du serpent. )
TkHandler_Combo_1_CanKeep.py
import tkinter as tk
# Common parts in my GitHub
# https://github.com/dede-20191130/CreateToolAndTest
from Commons.TkHandler_Combo_1 import TkHandler_Combo_1
class TkHandler_Combo_1_CanKeep(TkHandler_Combo_1):
    """
Implémentation d'une case à cocher pour ne pas quitter l'outil même après avoir appuyé sur le bouton de processus
    """
    def __init__(self, rootTitle='Titre', rootGeometry='640x480'):
        super(TkHandler_Combo_1_CanKeep, self).__init__(rootTitle, rootGeometry)
        self.keeping_check = None
        self.bl = None
    def create_keep_check(self, text='check box', is_initial=True):
        self.bl = tk.BooleanVar(value=is_initial)
        self.keeping_check = tk.Checkbutton(self.frame, text=text, variable=self.bl)
        self.keeping_check.pack()
        self.bl = tk.BooleanVar(value=is_initial)
        self.keeping_check = tk.Checkbutton(self.frame, text=text, variable=self.bl)
BooleanVar est une variable de widget. Référence: https://suzutaka-programming.com/tkinter-variable/
Variables pouvant être spécifiées dans la variable -text et les options -variable.
Vous pouvez modifier dynamiquement la chaîne d'étiquette et obtenir la valeur saisie.
Réécrit comme suit.
QuickBrowsing.py
import os
import subprocess
import sys
#Réinitialiser le chemin de recherche du module
#Rendre possible de démarrer en double-cliquant
sys.path.append(os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH") + r"\PycharmProjects\CreateToolAndTest")
# Common parts in my GitHub
# https://github.com/dede-20191130/CreateToolAndTest
from Commons.JsonHandler import JsonHandler
from Commons.TkHandler_Combo_1_CanKeep import TkHandler_Combo_1_CanKeep
import webbrowser
from time import sleep
# global
jsonHandler = None
siteList = None
tkHandler = None
siteName = None
def Main():
    global jsonHandler
    global siteList
    global tkHandler
    global siteName
    #Acquisition d'objets
    jsonHandler = JsonHandler(
        r'C:/Users/UserName/MyFolder/Foo.json')
    siteList = jsonHandler.getAll_OneNest()
    #Affichage du formulaire
    tkHandler = TkHandler_Combo_1_CanKeep('Navigation rapide', '640x200')
    tkHandler.createFrame()
    tkHandler.createLabel('Sélectionnez un site Web pour l'affichage par lots.')
    tkHandler.createCombo(myValue=siteList)
    tkHandler.create_keep_check('Vérifiez si cela ne se termine pas après l'exécution.')
    tkHandler.createButton(myFunc=get_name_and_open)
    tkHandler.mainLoop()
def get_name_and_open(argName=''):
    global tkHandler
    global siteName
    if not tkHandler.bl.get():
        tkHandler.onClosing()
    siteName = argName
    open_in_order()
def open_in_order():
    global jsonHandler
    global siteName
    #Si le site n'est pas défini, il se termine normalement
    #Si la page Web n'est pas enregistrée, elle se termine normalement
    if siteName == None or not jsonHandler.getParam_TwoNest(siteName, 'OnlyOpenPage'):
        exit(0)
    #Ouvrez les sites Web dans l'ordre
    subprocess.Popen("start chrome /new-tab www.google.com --new-window", shell=True)
    sleep(1)
    browser = webbrowser.get(r'"' + os.getenv(r'ProgramFiles(x86)') + \
                             r'\Google\Chrome\Application\chrome.exe" %s')
    for url in jsonHandler.getParam_TwoNest(siteName, 'PageSet'):
        browser.open(url)
if __name__ == '__main__':
    Main()
    if not tkHandler.bl.get():
        tkHandler.onClosing()
Vous pouvez librement cocher et décocher les cases à cocher sur l'interface graphique. Si le bouton d'exécution est enfoncé lorsqu'il est activé, la méthode onclose n'est pas appelée.