Forum Archive

It's my first program for Pythonista

Cheng

It use in widget.
1.get date in a json file
2.get date from datetime
3.If the two dates are the same, read the json file,else update the json file and read it.
4.put the result in widget.

I am a newbie, please advise.

And I want to ask how to display multiple buttons in the widget and can turn pages?

# -*- coding: UTF-8 -*-

import requests
import re
import json
import datetime
import appex, ui

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
'Accept-Language': 'zh-CN,zh;q=0.9'
}


def get_page(url):
    response = requests.get(url, headers=headers)
    data = json.loads(response.text)
    return data


def write_file(data):
    with open(r'./mryj.json', 'w+') as f:
        f.write(json.dumps(data))
        print('文件已更新')


def get_filedate():
    try:
        with open(r'./mryj.json', 'r') as f:
            d = json.loads(f.read())
            filedate = d['dateline']
            print('文件日期 ', filedate)
    except:
        with open(r'./mryj.json', 'w+') as f:
            d = f.write(json.dumps({'dateline':'None'}))
            filedate = 'None'
    return filedate


def get_datetime():
    timenow = datetime.datetime.now().strftime('%Y-%m-%d')
    print('实际日期 ', timenow)
    return timenow



def layout():
    with open(r'./mryj.json', 'r') as f:
        data = json.loads(f.read())
    v = ui.View()
    text = ui.TextView(font=('Didot', 15))
    text.text = '   ' + data['note'] + '\n' + '  ' + data['content']
    text.editable = False
    text.selectable = False
    v.add_subview(text)
    appex.set_widget_view(text)

url = 'http://open.iciba.com/dsapi/'

filedate = get_filedate()
timenow = get_datetime()
if filedate == timenow:
    print('时间相同,读取文件')
    layout()
else:
    print('时间不同,更新文件')
    data = get_page(url)
    write_file(data)
    layout()

ccc
def get_page(url):
    return requests.get(url, headers=headers).json()
cvp

@Cheng you have to use v instead of text as widget_view

appex.set_widget_view(v)

and add buttons as subviews of v, like you did with textview

Cheng

@cvp Thank u.
Can you give me an example with the following code?
In a widget display both button1 and button2.

v = ui.View()
button1 = ui.Button(title='button1')
button2 = ui.Button(title='button2')
v.add_subview(button)
appex.set_widget_view(v)
brumm

button1.frame = (x, y,width,height)
button2.frame = (x, y,width,height)

v.add_subview(button1)
v.add_subview(button2)
Cheng

@brumm I succeeded
I didn't set the position when I tried it, the second button blocked the first button.
Thank U.

cvp

@Cheng you are right, and you made a little error with add_subview(button) instead (button1) and (button2)

mikael

@Cheng, for paging, how long are your lines?

Cheng

@mikael I plan to do less than 50 lines.
Each button is actually a hyperlink that allows browse the web in the widget.That's my idea.

Cheng

And another problem is Button.action
The function must take a single sender parameter.
I want different buttons to correspond to different links.

ccc
def button_action(sender):
    if sender.title =="Apple":
        url = "https://www.apple.com"
    elif sender.title =="Google":
        url = "https://www.google.com"
Cheng

@ccc there’s many links in a file, Function cannot pass variables.

ccc

The button (sender) has attributes... Here I used sender.title but you could also add a .url attribute to your buttons...

button1.url = "https://www.apple.com"

cvp

@ccc "les grands esprits se rencontrent" 😂, I just wrote

import ui
v = ui.View()
v.frame = (0,0,200,200)
def b_action(sender):
    print(sender.url)
b1 = ui.Button(title='Apple', frame = (10,10,80,32), url='https://www.apple.com', action=b_action)
v.add_subview(b1)
b2 = ui.Button(title='Google', frame = (100,10,80,32), url='https://www.google.com', action=b_action)
v.add_subview(b2)
v.present('sheet')
Cheng

@ccc my button url is a variable.

def button_tapped(sender):
    self.webbrowser.open(href) #???
v=ui.View(frame=(0,0,300,400))
with open('./wb.json', 'r') as f:
    wb = f.readlines()
    for i in range(0,20):
        wbi = wb[i]
        title = json.loads(wbi)['title']
        href = json.loads(wbi)['href']  #href is the button url
        button = ui.Button(title=title)
        button.action = button_tapped 
        button.frame = (0,i*25,450,20)
        v.add_subview(button)

I think I need 20 button.tapped functions.

ccc

Do you use GitHub? A repo with more complete code would help a lot. You definitely do not need 20 actions.

cvp

@Cheng I'm sure @ccc will answer in one minute, thus...😀

cvp

@Cheng when you create your buttons, set

button.href = href

and you want to use it, in action, do

.......open(sender.href)

Cheng

I’ll try.
Thank you @ccc and thank @cvp .
Also thanks to Google Translate.😅

cvp

@Cheng Sorry for the French sentence, it was only a joke for @ccc

ccc

You can write your data to a .json file and then read it back into a dict...

#!/usr/bin/env python3

import json

data = {
    "Apple": "https://www.apple.com",
    "Google": "https://www.google.com",
    "IBM": "https://www.ibm.com",
}

with open("buttons.json", "w") as out_file:
    json.dump(data, out_file)

del data  # remove the in-memory instance

with open("buttons.json") as in_file:
    data = json.load(in_file)

for i, (title, url) in enumerate(data.items()):
    print(i, title, url)
Cheng

I almost finished my code.
But still have a problem
When I tapped button0 TAP ,button0 does not disappear as sender.title = ‘ ‘, and the new button has displayed.
And how to use remove_subview(button0)?

import requests
import re
import json
import ui, appex
import webbrowser

headers={
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}
data = {
    'cate':'realtimehot'
}


def get_page(url):
    response = requests.get(url)
    html = response.text
    #print(html)
    return html


def parse_html(html):
    #top = re.findall(r'class="icon-top"></i></td>.*?<td class="td-02">.*?<a href="(.*?)" target="_blank">(.*?)</a>.*?</td>', html, re.S)
    data = re.findall(r'ranktop">(.*?)</td>.*?<a href="(.*?)" target="_blank">(.*?)</a>.*?<span>(.*?)</span>', html, re.S)
    #print(top)
    #print(data)
    return data


def write_data(data):
    with open(r'./wb.json', 'w', encoding='gbk') as f:
        for i in data:
            f.writelines(json.dumps(i) + '\n')
    print('done')


def get_json(items, host):
    for item in items:
        yield {
            'rank': item[0],
            'href': host + item[1],
            'title': item[2],
            'num': item[3],
        }

class control(ui.View):
    def __init__(self):
        self.frame=(0,0,400,600)
        appex.set_widget_view(self)


    def button_tapped1(self, sender):
        webbrowser.open(sender.href)


    def button_tapped(self, sender):
        sender.title = ''
        self.list()


    def layout(self):
        button0 = ui.Button(font=('<System>', 34), frame=(100,25,200,40), tint_color='red')
        button0.title = 'TAP'
        button0.action = self.button_tapped
        self.add_subview(button0)
        return button0


    def list(self):
        host = 'https://s.weibo.com'
        url = 'http://s.weibo.com/top/summary?'
        html = get_page(url)
        data = parse_html(html)
        wb = get_json(data, host)
        write_data(wb)
        with open('./wb.json', 'r') as f:
            wb = f.readlines()
        for i in range(0,23):
            wbi = wb[i]
            title = json.loads(wbi)['title']
            href = json.loads(wbi)['href']
            #title = json.loads(wbi)
            button = ui.Button(title=title, font=('<System>', 18))
            button.href = 'Alook://' + href
            button.action = self.button_tapped1
            button.frame = (0,i*25,400,20)
            self.add_subview(button)


def main():
    control()


if __name__ == '__main__':
    main()

ccc
# This button will self destruct.
def button_tapped1(self, sender):
        webbrowser.open(sender.href)
        self.remove_subview(sender)
cvp

The real problem comes from the fact that layout is called two times, thus there are two buttons with TAP title...
Create your button0 in init and remove the layout def.
Or rename your layout into layoutx and call it in init:

    def __init__(self):
        self.frame=(0,0,400,600)
        appex.set_widget_view(self)
        self.layoutx()
.
.
.
    def layoutx(self):
Cheng

@cvp You are right . Function name can't be written casually.