tkinter-TinUI-xml实战(3)获取博客链接

引言

CSDN是一个充满各种编程知识的技术网站,无论是小白还是大神都可以在这里找到对自己有用的文章。一些人有自己关注的博主,那是因为这个博主的系列文章正好对上了自己的胃口。那么现在我们将开发一个基于tkinter的小程序,以获取某一个博主的文章,并用链接形式呈现到TinUI界面上。

我不是做爬虫的,只是使用类似的功能代码而已。

声明

本项目属于作者原创,禁止用于非法途径。功能代码部分十分简单,因此着重说明界面部分的编写。

本项目使用的TinUI为我开源并维护在GitHub上的主文件——TinUI.py。当然,使用PYPI中下载安装的tinui也可以

文件结构

本次使用的文件结构如下:

在这里插入图片描述

  • main-get.xml - 主界面
  • tinui.py - TinUI界面核心支持
  • 博客获取.py - 本次项目文件

编写界面

在本项目中,界面主要由两部分组成:

  1. 交互部分:显示输入框等交互控件
  2. 显示部分:显示获取到的所有博客链接

交互界面(main-get.xml)

这个交互界面十分简单,只有两个主要控件,与本系列第一篇文章“天气预报”的交互部分一模一样。

以下是main-get.xml的内容:

<!--基于TinUI的CSDN博主博客列表获取-->
<tinui ver='1.0'>
    <line>
        <entry width='400' text='https://blog.csdn.net/[name]/article/list/[page]'>entry</entry>
        <button text='开始' command='self.funcs["go"]'>button</button>
    </line>
    <line>
        <label text='博客列表>>>' outline=''></label>
    </line>
</tinui>

链接显示界面

因为我们无法确定博客文章的数量,所以没办法将界面布局写在xml文件中。

虽然我们需要动态添加界面布局元素,但是我们可以确定我们显示的所有链接(link)控件元素的排列方式:

<tinui>
    <line>
        <link url='url' text='text'></link>
    </line>
    <line>
        <label text='description'></label>
    </line>
    ...
</tinui>

这个类xml形式的字符串,将在循环代码中动态添加。在源码中,使用__go函数来执行这个链接显示界面的控件渲染:

def __go():
    button[1]()
    url=entry.get()
    if url=='':
        return
    urls_xml='<tinui>'
    result=request.urlopen(url)
    html=result.read().decode('utf-8')
    links=read_html(html)
    x2.clean()
    for link in links:
        add=f'<line><link url="{link[0]+"?spm="+link[1]}" text="{link[2]}"></link></line><line><label text="{link[3]}" font="微软雅黑 10"></label></line>'
        urls_xml+=add
    urls_xml+='</tinui>'
    x2.loadxml(urls_xml)

变量add就是我们动态添加的控件xml描述文本。

编写TinUIXml-IDO

这次基本没什么前后端融合代码:

#=====IDO=====
u=BasicTinUI(root,height=50)#主界面
u.pack(fill='both',expand=True)
x=TinUIXml(u)
u2=TinUI(root)#显示链接
u2.pack(fill='both',expand=True)
x2=TinUIXml(u2)
#in
x.funcs['go']=go
#during
with open('main-get.xml',mode='r',encoding='utf-8') as f:
    xml=f.read()
x.loadxml(xml)
#out
entry=x.tags['entry'][0]
button=x.tags['button'][2]

完整代码

网络请求与正则解析部分相信大家都很熟悉了,这里直接给出完整代码:

from urllib import request
from tkinter import Tk
import re
import time
import random
from threading import Thread
from tinui import *


def go(event):
    Thread(target=__go).start()


def __go():
    button[1]()
    url=entry.get()
    if url=='':
        return
    urls_xml='<tinui>'
    result=request.urlopen(url)
    html=result.read().decode('utf-8')
    links=read_html(html)
    x2.clean()
    for link in links:
        add=f'<line><link url="{link[0]+"?spm="+link[1]}" text="{link[2]}"></link></line><line><label text="{link[3]}" font="微软雅黑 10"></label></line>'
        urls_xml+=add
    urls_xml+='</tinui>'
    x2.loadxml(urls_xml)

def read_html(html):#解析HTML
    article_div=re.findall('\<div class="article-item-box csdn-tracking-statistics".*?\>(.*?)\</div\>',html,re.S|re.M)
    links=[]
    for article in article_div:
        link=re.search('\<a.*?href="(.*?)".*?"spm":"(.*?)".*?\>',article,re.S|re.M)
        title=re.search('</span>(.*?)</a>',article,re.S|re.M)
        title=title.group(1)[11:-9]
        des=re.search('<p.*?>(.*?)</p>',article,re.S|re.M)
        links.append((link.group(1),link.group(2),title,des.group(1)[9:-7]))
    return links


root=Tk()
root.title('CSDN博客列表获取')
root.geometry('600x600')

u=BasicTinUI(root,height=50)
u.pack(fill='both',expand=True)
x=TinUIXml(u)
u2=TinUI(root)#显示链接
u2.pack(fill='both',expand=True)
x2=TinUIXml(u2)
#in
x.funcs['go']=go
#during
with open('main-get.xml',mode='r',encoding='utf-8') as f:
    xml=f.read()
x.loadxml(xml)
#out
entry=x.tags['entry'][0]
button=x.tags['button'][2]

root.mainloop()

效果

在这里插入图片描述

在这里我们强制使用博客列表的网页网址。


2022-5-15更新

本次更新如下:

  1. 使用TinUI3.X
  2. 在窗口右侧显示文章页面

所做更改如下:

  • 使用最新版本的TinUI
  • 使用tkinterie拓展库
  • 添加网页打开逻辑
  • 修改x2中的xml文本,使其支持目标函数

新代码:

from urllib import request
from tkinter import Tk,Frame
import re
import time
import random
from threading import Thread as pyThread
from tinui import *

from tkinterie.tkinterIE import WebView
import clr
clr.AddReference('System.Threading')
from System.Threading import Thread,ApartmentState,ThreadStart


def openurl(url):
    wb.navigate(url)

def go(event):
    pyThread(target=__go).start()


def __go():
    def end():
        e=u2.bbox('all')
        if e==None:
            return 3
        else:
            return e[-1]
    button[1]()
    url=entry.get()
    if url=='':
        return
    urls_xml='<tinui>'
    result=request.urlopen(url)
    html=result.read().decode('utf-8')
    links=read_html(html)
    x2.clean()
    for link in links:
        add=f'''<line><link url="{link[0]+"?spm="+link[1]}" text="{link[2]}" command="self.funcs['openurl']"></link></line><line><label text="{link[3]}" font="微软雅黑 10"></label></line>'''
        urls_xml+=add
    urls_xml+='</tinui>'
    x2.loadxml(urls_xml)

def read_html(html):#解析HTML
    article_div=re.findall('\<div class="article-item-box csdn-tracking-statistics".*?\>(.*?)\</div\>',html,re.S|re.M)
    links=[]
    for article in article_div:
        link=re.search('\<a.*?href="(.*?)".*?"spm":"(.*?)".*?\>',article,re.S|re.M)
        title=re.search('</span>(.*?)</a>',article,re.S|re.M)
        title=title.group(1)[11:-9]
        des=re.search('<p.*?>(.*?)</p>',article,re.S|re.M)
        links.append((link.group(1),link.group(2),title,des.group(1)[9:-7]))
    return links


def main():
    global root,u,x,u2,x2,entry,button,wb
    root=Tk()
    root.title('CSDN博客列表获取')
    root.geometry('1200x600')
    frame=Frame(root)
    frame.pack(fill='y',side='left')

    u=BasicTinUI(frame,height=100,width=580)
    u.pack(fill='both',expand=True)
    x=TinUIXml(u)
    u2=TinUI(frame,width=580)#显示链接
    u2.pack(fill='y',expand=True)
    x2=TinUIXml(u2)
    #in
    x.funcs['go']=go
    x2.funcs['openurl']=openurl
    #during
    with open('main-get.xml',mode='r',encoding='utf-8') as f:
        xml=f.read()
    x.loadxml(xml)
    #out
    entry=x.tags['entry'][0]
    button=x.tags['button'][2]

    wb=WebView(root,500,500)
    wb.pack(side='right',fil='both',expand=True)
    wb.update()

    root.mainloop()

if __name__=='__main__':
    t = Thread(ThreadStart(main))
    t.ApartmentState = ApartmentState.STA
    t.Start()
    t.Join()

效果:
在这里插入图片描述


结语

加上本系列提一篇的“天气预报”,这是第二次将TinUI与网络HTML解析相结合,体现了TinUI强大的融合能力。下次准备写一个本地程序。开始你的tkinter编程之路吧。

🔆tkinter创新🔆

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值