使用 Tkinter 写一个爬虫的辅助软件——HTTP测试工具(Python)

介绍

今天来使用 tkinter 写一个爬虫的 http 测试工具,当然市面上也有许多稳定的测试工具可以使用,本次主要的学习 tkinter 界面开发的使用方法以及爬虫的相关的一些基本操作;本来是准备使用 Qt 制作的,但是制作完后发现程序不稳定,经常卡死,最后选择了 tkinter 再开发一个;以下就是我的开发过程,大家谁知道QT为什么会经常卡死,或者有解决方法的可以私聊讨论以下。

界面

大家先看一下界面效果图:
主界面:
辅助工具的核心主界面
辅助功能界面:
一 、Curl 转换 为Python代码功能界面:

Curl 转换
二 、 验证码识别界面:
请添加图片描述

程序功能介绍:

1、支持 http2.0http1.0 进行转换测试;
2、UA 允许 随机生成;
3、忽略 证书验证;
4、支持 Xpath 解析数据;
5、允许代理测试;
6、允许 身份认证测试;
7、允许阻止 重定向;
8、对于展示结果 可以进行选择;
9、可以使用 Curl 快速生成代码进行访问测试;
10、可以复制转换后的Python代码;
11、支持部分验证码的 检测识别。

使用到的库

import cv2
import ddddocr
import os
import cchardet
import datetime
import fake_useragent
import httpx
import threading
from tkinter import *
from PIL import ImageTk, Image
from curl2py import curlParseTool
from tkinter import filedialog
from tkinter import ttk, scrolledtext, simpledialog
from parsel import Selector

界面 设计

主窗口设计

一、设计多窗口

将三个功能分开设计

tabControl = ttk.Notebook(self.app)  # Create Tab Control
http_chkout = ttk.Frame(tabControl)  # http 窗口
tabControl.add(http_chkout, text='HTTP')
Curl = ttk.Frame(tabControl)
tabControl.add(Curl, text='CURL')
Yzm = ttk.Frame(tabControl)
tabControl.add(Yzm, text='验证码')

二、 主窗口

设计主要的 HTTP 测试窗口

def http_check(self, http_chkout):
    # ----------------- http 测试界面 ------------------ #
    chec = ttk.Frame(http_chkout)
    chec.grid(column=0, row=0)
    # 请求方式列表
    self.method = ttk.Combobox(chec, width=8)
    self.method['values'] = ('GET', 'POST', 'PUT')
    self.method.grid(column=0, row=1)
    self.method.current(0)  # 设置初始显示值,值为元组['values']的下标
    self.method.config(state='readonly')  # 设为只读模式
    # URL
    self.url = ttk.Entry(chec, width=88)
    self.url.grid(column=1, row=1, sticky='W')
    search = ttk.Button(chec, text="测试", width=10, command=self.search)  # 搜索
    search.grid(column=2, row=1)
    # 状态    states
    states = ttk.Frame(http_chkout)
    states.grid(column=0, row=1, ipadx=1, sticky=W)
    state1 = ttk.Frame(states)
    state1.grid(column=0, row=0, pady=10, padx=20, sticky=W)
    state2 = ttk.Frame(states)
    state2.grid(column=1, row=0, pady=10, padx=20, sticky=W)
    state3 = ttk.Frame(states)
    state3.grid(column=2, row=0, pady=10, padx=20, sticky=W)
    # 上面 三个  框架
    Label(state1, text="请求头").grid(column=0, row=0)
    add = ttk.Button(state1, text="➕", width=5, command=self.add)
    add.grid(column=1, row=0)
    del_e = ttk.Button(state1, text="➖", width=5, command=self.dele)
    del_e.grid(column=2, row=0)
    curl = ttk.Button(state1, text="curl", width=5, command=self.Curl)
    curl.grid(column=3, row=0)
    self.table_header = ttk.Treeview(state1, show="headings", height=13, columns=("name", "value"))
    self.table_header.column("name", width=65, anchor='center')
    self.table_header.column("value", width=130, anchor="w")
    self.table_header.heading("name", text="name")
    self.table_header.heading("value", text="value")
    self.table_header.grid(column=0, row=1, columnspan=4, pady=5)  # column 列

    Label(state2, text="DATA ( param )").grid(column=0, row=0)
    self.Data = scrolledtext.ScrolledText(state2, width=33, height=10, wrap=WORD)
    self.Data.grid(column=0, row=2)
    Label(state2, text="JSON").grid(column=0, row=3)
    self.Data = scrolledtext.ScrolledText(state2, width=33, height=10, wrap=WORD)
    self.Data.grid(column=0, row=4)

    Label(state3, text="特殊选择").grid(column=0, row=0, columnspan=3)
    self.http2 = BooleanVar()  # HTTP 版本选择
    Checkbutton(state3, text="Http2.0 (默认1.0)", variable=self.http2).grid(column=0, row=1, sticky=W, columnspan=3)
    self.ua = BooleanVar()  # 随机 UA
    ua = Checkbutton(state3, text="随机UA", variable=self.ua)
    ua.select()
    ua.grid(column=0, row=2, sticky=W, columnspan=3)
    self.Ajax = BooleanVar()
    Checkbutton(state3, text="Ajax XMLHttp", variable=self.Ajax).grid(column=0, row=3, sticky=W, columnspan=3)
    self.verify = BooleanVar()
    verify = Checkbutton(state3, text="忽略证书验证", variable=self.verify)
    verify.select()
    verify.grid(column=0, row=4, sticky=W, columnspan=3)
    self.Xpath = BooleanVar()
    Checkbutton(state3, text="XPATH :", variable=self.Xpath, command=self.small_xpath).grid(column=0, row=5,
                                                                                            sticky=W)
    self.xpath = ttk.Entry(state3, width=20)
    self.xpath.insert(0, "如: //div[@id='xxxx']")
    self.xpath.configure(state='readonly')
    self.xpath.grid(column=1, row=5, sticky=W, columnspan=2)

    Label(state3, text="TimeOut: ").grid(column=0, row=6, sticky=W)
    self.TimeOut = Spinbox(state3, from_=3, to=30, width=5)
    self.TimeOut.grid(column=1, row=6, sticky=W)
    txt_xpath = ttk.Button(state3, text="Xpath", width=10)
    txt_xpath.grid(column=2, row=6, sticky=E)
    self.Proxies = BooleanVar()  # 代理
    proxies = Checkbutton(state3, text="代理 :", variable=self.Proxies, command=self.proxie)
    proxies.grid(column=0, row=7, sticky=W)
    self.proxies = ttk.Entry(state3, width=20)
    self.proxies.insert(0, "如:000.000.000.000:80")
    self.proxies.configure(state='readonly')
    self.proxies.grid(column=1, row=7, sticky=W, columnspan=2)
    self.Auth = BooleanVar()  # 账号密码
    auth = Checkbutton(state3, text="Auth :", variable=self.Auth, command=self.author)
    auth.grid(column=0, row=8, sticky=W)
    self.auth = ttk.Entry(state3, width=20)  # setPlaceholderText
    self.auth.insert(0, "如:username;password")
    self.auth.configure(state='readonly')
    self.auth.grid(column=1, row=8, sticky=W, columnspan=2)

    self.Redirect = BooleanVar()
    redirect = Checkbutton(state3, text="是否允许  重定向", variable=self.Redirect)  # 重定向
    redirect.select()
    redirect.grid(column=0, row=9, sticky=W, columnspan=3)

    result_data = ttk.LabelFrame(state3, text="展示结果类型")
    result_data.grid(column=0, row=10, columnspan=3)
    self.result = IntVar()
    self.result.set(99)

    Radiobutton(result_data, text="Json", variable=self.result, value=1).grid(column=0, row=9, sticky=W)
    Radiobutton(result_data, text="Text", variable=self.result, value=2).grid(column=1, row=9, sticky=W)
    r = Radiobutton(result_data, text="None", variable=self.result, value=3)
    r.select()
    r.grid(column=2, row=9, sticky=W)

    # 展示结果
    # show = ttk.Frame(http_chkout)
    # show.grid(column=0, row=2, pady=10, padx=20, sticky=W, columnspan=3)
    self.Show = scrolledtext.ScrolledText(states, width=10, height=20, wrap=WORD)
    self.Show.grid(column=0, row=1, sticky='WE', columnspan=3, padx=10)
    

三、Curl 辅助 窗口

def curl_(self, Curl):
    # ----------------- curl 测试界面 ------------------ #
    curl = ttk.Frame(Curl)
    curl.grid(column=0, row=0, pady=10, padx=20, sticky=W)
    Label(curl, text="CURL 命令").grid(column=0, row=0)
    self.curl_u = scrolledtext.ScrolledText(curl, width=105, height=20, wrap=WORD)
    self.curl_u.grid(column=0, row=1)
    Label(curl, text="CURL 转换结果").grid(column=0, row=2)
    self.curl_result = scrolledtext.ScrolledText(curl, width=105, height=20, wrap=WORD)
    self.curl_result.grid(column=0, row=3)

    self.curl_u.bind("<Key>", self.curl_stran)
    self.curl_u.bind("<Control-Key-v>", self.curl_stran)

四、最后的验证码窗口设计

def YZM(self, Yzm):
   org_init = """请选择图片放入"""
   pic = ttk.Frame(Yzm)
   pic.grid(column=0, row=0, pady=10, padx=20, sticky=W)
   self.pic_yzm1 = Label(pic, relief="sunken", text=org_init)
   self.pic_yzm1.bind("<Button-1>", self.open_file)
   self.pic_yzm1.grid(column=0, row=0)
   self.pic_yzm2 = Label(pic, relief="sunken", text=org_init)
   self.pic_yzm2.bind("<Button-1>", self.open_file2)
   self.pic_yzm2.grid(column=1, row=0)
   txt = "========================================================================================"
   Label(pic, width=107, height=1, text=txt).grid(column=0, row=1, columnspan=2)
   push_button = ttk.Frame(Yzm)
   push_button.grid(column=0, row=1, pady=10, padx=20, sticky=W)

   # 请求方式列表
   self.code_type = ttk.Combobox(push_button, width=10)
   self.code_type['values'] = ('字符验证码', '滑块验证码', '汉字验证码', '点选验证码')
   self.code_type.grid(column=0, row=0)
   self.code_type.current(0)  # 设置初始显示值,值为元组['values']的下标
   self.code_type.config(state='readonly')  # 设为只读模式
   Label(push_button, padx=10, text="验证码结果:").grid(column=2, row=0)
   Label(push_button, padx=10, text="").grid(column=5, row=0)
   ttk.Button(push_button, text="处理验证码", width=10, command=self.ORC).grid(column=6, row=0)

   self.old_ddddorc = IntVar()
   dc = Checkbutton(push_button, text="老版本模型", variable=self.old_ddddorc)
   dc.deselect()
   dc.grid(column=7, row=0, sticky=W)

   self.code_result = ttk.Entry(push_button, x=10, width=50)
   self.code_result.grid(column=4, row=0, sticky='W')

   self.Identify_code = scrolledtext.ScrolledText(Yzm, width=105, height=15, wrap=WORD)
   self.Identify_code.grid(column=0, row=2)

以上便是 界面的 设计核心代码

功能设计

1、请求 访问的方法 我选择使用的是支持 http1.0http2.0 相互转换的请求方式,选择了 httpx
2、Curl 转换方面 我使用的 是 curl2py
3、 验证码 识别 选择的 是 ddddocr
4、爬虫 数据解析使用的是 parsel

关于本次 程序设计 1.0 版本 只做了 GET 请求的测试 其他的请求方式还没有设计,大家可以根据自己习惯进行设计开发

一、http 请求

    def requests(self, method, url, header_user, http_v):
        proxies_ = self.proxies_()
        auth = self.Auth_result()
        verify = self.verify_()
        if "http" in url:
            if http_v:
                client = httpx.Client(http2=True, verify=verify, proxies=proxies_, auth=auth)
            else:
                client = httpx.Client(verify=verify, proxies=proxies_, auth=auth)
            if method == "GET":
                res_dic = self.get_requets(client, url, header_user)
                if res_dic["stauts"] == 200:
                    res = res_dic["res"]
                    html_ = Selector(res.content.decode(encoding=cchardet.detect(res.content)["encoding"]))
                    show_result = self.radCall()
                    self.insert_(word="************* result ***************")
                    if show_result == "text":
                        if self.Xpath.get():
                            show_ = "\n".join(html_).xpath("//text()").getall()
                            self.insert_(word=show_, h=False)
                        else:
                            self.insert_(word=html_.get(), h=False)
                    elif show_result == "json":
                        try:
                            json_ = res.json()
                            self.insert_(word=json_, h=False)
                        except:
                            self.insert_(word="数据 格式 获取错误 请到原数据确认格式, 或确认请求参数是否正确!!!")
                    else:
                        self.insert_(word="未 选择 正确的展示格式 !!!", h=False)
                else:
                    self.insert_(word="请求错误 ::::》》》》")
            elif method == "POST":
                self.insert_(word="未开发项目 ::: 》》》》")
        else:
            self.insert_(word="未检测到 http(https) 地址====================")

        self.insert_(word='************* Over !! ***************')

二、CURL 转换

使用 Curl 命令转换为 Python 代码; 可以更加方便的快速开发爬虫代码功能

    def curl_stran(self, event):
        li_org = """#######################################
#      The generated by curl2py.      
#      author:小小明                  
#######################################"""
        li_s = """# author: Sheild
# Createtime: {}""".format(datetime.datetime.now())
        world = self.curl_u.get(1.0, 'end')
        self.curl_u.see(END)
        if is_Chinese(world) is None:
            if ("-h" in world) or ("-H" in world):
                try:
                    value = curlParseTool.curlCmdGenPyScript(world).replace(li_org, li_s)
                    self.curl_result.delete(1.0, END)
                    self.curl_result.insert("insert", value)
                    self.curl_result.see(END)
                except:
                    pass
            else:
                pass
        else:
            pass

三、验证码 识别 核心代码

    def ORC(self):
        if self.pic_org_ is None:
            pass
        else:
            code_type = self.code_type.get()
            print(code_type)
            if code_type == "字符验证码":
                f = self.pic_org_.replace("\\", "/")
                code_file = f"""import ddddocr
orc =ddddocr.DdddOcr(%s)
with open('{f}', 'rb') as f:
    img_bytes = f.read()
    f.close()
result_num = orc.classification(img_bytes)
print(result_num)"""
                if self.old_ddddorc.get():
                    orc = ddddocr.DdddOcr(old=True)     # old=True
                    code_file = code_file % ("old=True",)
                else:
                    orc = ddddocr.DdddOcr()
                    code_file = code_file % ("",)
                with open(self.pic_org_, 'rb') as f:
                    img_bytes = f.read()
                    f.close()
                result_num = orc.classification(img_bytes)
                self.code_result.delete(0, END)
                self.code_result.insert("insert", result_num)
                self.Identify_code.delete(1.0, END)
                self.Identify_code.insert("insert", code_file)
            elif code_type == "点选验证码":
                det = ddddocr.DdddOcr(det=True)
                code_file = f"""import ddddocr
det = ddddocr.DdddOcr(det=True)
with open('{self.pic_org_}', 'rb') as f:
    img_bytes = f.read()
    f.close()
poses = det.detection(img_bytes)
print(poses)
################# 结果图片的保存查看  #################
from cv2 import cv2
im = cv2.imread(self.pic_org_)
for box in poses:
    x1, y1, x2, y2 = box
    im = cv2.rectangle(im, (x1, y1), (x2, y2), color=(0, 0, 255), thickness=2)
cv2.imwrite("result.jpg", im)
"""
                with open(self.pic_org_, 'rb') as f:
                    img_bytes = f.read()
                    f.close()
                poses = det.detection(img_bytes)
                print(poses)
                self.code_result.delete(0, END)
                self.code_result.insert("insert", poses)
                self.Identify_code.delete(1.0, END)
                self.Identify_code.insert("insert", code_file)
                im = cv2.imread(self.pic_org_)

                for box in poses:
                    x1, y1, x2, y2 = box
                    im = cv2.rectangle(im, (x1, y1), (x2, y2), color=(0, 0, 255), thickness=2)
                cv2.imwrite("result.jpg", im)
                img_gif = Image.open("result.jpg")
                photo = ImageTk.PhotoImage(img_gif)
                self.pic_yzm2.config(image=photo)
                self.pic_yzm2.image = photo

总结

测试效果图

主界面爬虫测试:
请添加图片描述
Curl 转换 测试:
请添加图片描述

验证码 测试 效果:
请添加图片描述

本文仅供 学习交流
如果需要完整代码 可以私信我,或者下面链接下载源码;

完整源代码下载地址:https://download.csdn.net/download/qq_39832685/85026074

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

渊季

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值