从过程向标签输出文本
谢谢你们到目前为止的帮助!还有一个问题解决了就可以收尾了。
我找不到办法把文本输出到标签上,如果可以的话,我还想在那个标签里显示一个链接,让用户可以打开网页。
我试着定义新的程序来实现这个功能,但在构建时虽然可以指定文本,之后我却无法更改它!我总是收到“变量未定义”的错误,显然我在错误的地方操作了!
import kivy
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.spinner import Spinner
from bs4 import BeautifulSoup
from urllib import request
import sys, traceback
from functools import partial
import re
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.image import Image
class DSFRSapp(App):
def build(self):
self.root = FloatLayout()
i = Image(source='DSFRSLogo.png',
allow_stretch=True,
pos_hint = ({'center_x':0.5, 'y': .25}))
spinner = Spinner(text='Select a Station',
values=('Appledore','Axminster','Bampton','Barnstaple','Bere Alston','Bideford','Bovey Tracey','Braunton','Bridgwater','Brixham','Buckfastleigh','Budleigh Salterton','Burnham on sea','Camels Head','Castle Cary','Chagford','Chard','Cheddar','Chulmleigh','Colyton','Combe Martin','Crediton','Crewkerne','Crownhill','Cullompton','Dartmouth','Dawlish','Exeter Danes Castle','Exeter Middlemoor','Exmouth','Frome','Glastonbury','Greenbank','Hartland','Hatherleigh','Holsworthy','Honiton','Ilfracombe','Ilminster','Ivybridge','Kingsbridge','Kingston','Lundy Island','Lynton','Martock','Minehead','Modbury','Moretonhampstead','Nether Stowey','Newton Abbot','North Tawton','Okehampton','Ottery St Mary','Paignton','Plympton','Plymstock','Porlock','Princetown','Salcombe','Seaton','Shepton Mallet','Sidmouth','Somerton','South Molton','Street','Taunton','Tavistock','Teignmouth','Tiverton','Topsham','Torquay','Torrington','Totnes','USAR','Wellington','Wells','Williton','Wincanton','Witheridge','Wiveliscombe','Woolacombe','Yelverton','Yeovil'),
size_hint=(None, None),
size=(150, 44),
pos_hint = ({'center_x':0.5, 'y': 0.35}))
L = Label(text="Results will display here",
size_hint=(None, None),
pos_hint =({'center_x':0.5, 'y': 0.25}),
size=(150, 44))
self.root.add_widget(spinner)
self.root.add_widget(L)
self.root.add_widget(i)
spinner.bind(text=show_selected_value)
def show_selected_value(spinner, text):
FindIncident(text)
def FindIncident( sStation, *args ):
webpage = request.urlopen("http://www.dsfire.gov.uk/News/Newsdesk/IncidentsPast7days.cfm?siteCategoryId=3&T1ID=26&T2ID=35")#main page
soup = BeautifulSoup(webpage)
incidents = soup.find(id="CollapsiblePanel1") #gets todays incidents panel
Links = [] #create list call Links
for line in incidents.find_all('a'): #get all hyperlinks
Links.append("http://www.dsfire.gov.uk/News/Newsdesk/"+line.get('href')) #loads links into Links list while making them full links
n = 0
e = len(Links)
if e == n: #if no links available no need to continue
#output message to label
print("nothing found please try again later")
sys.exit(0)
sFound = False
while n < e: #loop through links to find station
if sFound: #if the station has been found stop looking
sys.exit(0)
webpage = request.urlopen(Links[n]) #opens link in list)
soup = BeautifulSoup(webpage) #loads webpage
if soup.find_all('p', text=re.compile(r'{}'.format(sStation))) == []:#check if returned value is found
#do nothing leaving blank gave error
a = "1" #this is pointless but stops the error
else:
print(soup.find_all('p', text=re.compile(r'{}'.format(sStation))))
WebLink = Links[n]
sFound = True # to avoid un needed goes through the loop process
n=n+1 # moves counter to next in list
if not sFound: #after looping process if nothing has been found output nothing found
print("nothing found please try again later ")
#output to label
return;
if __name__ =="__main__":
DSFRSapp().run()
我还得提一下,我有一个会显示的logo,我会在屏幕调整大小时更好地放置这些小部件。我想把背景颜色设为白色,可能加上一个细细的红色边框(就是想让它看起来更好看一些)。
如果你能回答这些问题中的任何一个,那就太好了!不过目前最重要的是把网页搜索的结果输出到标签上,而不是打印到控制台,最好还能带上链接(WebLink)。
再次感谢,一旦我解决了这些问题,我打算把这个程序交给我的消防服务部门,让消防员的伴侣们能大致了解消防员什么时候可能结束工作。不过这得等我能把它打包成安卓应用,也许还要找其他人把它移植到iOS,因为我没有Mac电脑。
1 个回答
0
我对代码做了一些修改,让它更符合Python的风格,特别是在循环方面。现在标签已经连接上了,但我还没有尝试调试你的网页抓取部分。这个你得自己再检查一下。
import kivy
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.spinner import Spinner
from bs4 import BeautifulSoup
from urllib import request
import sys, traceback
from functools import partial
import re
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.image import Image
from kivy.properties import ObjectProperty
kv = '''
<IncidentScreen>:
station: stationSpinner
results: resultsLabel
Image:
source:'DSFRSLogo.png'
allow_stretch:True
pos_hint: {'center_x':0.5, 'y': .25}
Spinner:
id: stationSpinner
text:'Select a Station'
values: ('Appledore','Axminster','Bampton','Barnstaple','Bere Alston','Bideford','Bovey Tracey','Braunton','Bridgwater','Brixham','Buckfastleigh','Budleigh Salterton','Burnham on sea','Camels Head','Castle Cary','Chagford','Chard','Cheddar','Chulmleigh','Colyton','Combe Martin','Crediton','Crewkerne','Crownhill','Cullompton','Dartmouth','Dawlish','Exeter Danes Castle','Exeter Middlemoor','Exmouth','Frome','Glastonbury','Greenbank','Hartland','Hatherleigh','Holsworthy','Honiton','Ilfracombe','Ilminster','Ivybridge','Kingsbridge','Kingston','Lundy Island','Lynton','Martock','Minehead','Modbury','Moretonhampstead','Nether Stowey','Newton Abbot','North Tawton','Okehampton','Ottery St Mary','Paignton','Plympton','Plymstock','Porlock','Princetown','Salcombe','Seaton','Shepton Mallet','Sidmouth','Somerton','South Molton','Street','Taunton','Tavistock','Teignmouth','Tiverton','Topsham','Torquay','Torrington','Totnes','USAR','Wellington','Wells','Williton','Wincanton','Witheridge','Wiveliscombe','Woolacombe','Yelverton','Yeovil')
size_hint: None, None
size: (150, 44)
pos_hint: {'center_x':0.5, 'y': 0.35}
on_text: app.show_selected_value()
Label:
id: resultsLabel
text:"Results will display here"
color: [0,0,0,1]
size_hint:(None, None)
pos_hint:{'center_x':0.5, 'y': 0.25}
size: (150, 44)
'''
class IncidentScreen(FloatLayout):
station = ObjectProperty(None)
results = ObjectProperty(None)
class DSFRSapp(App):
def build(self):
Builder.load_string(kv)
fl = IncidentScreen()
return fl
def show_selected_value(self):
incident = self.FindIncident(self.root.station.text)
if incident:
self.root.results.text = incident
else:
self.root.results.text = 'Try again later'
def FindIncident(self, sStation, *args ):
webpage = request.urlopen("http://www.dsfire.gov.uk/News/Newsdesk/IncidentsPast7days.cfm?siteCategoryId=3&T1ID=26&T2ID=35")#main page
soup = BeautifulSoup(webpage)
incidents = soup.find(id="CollapsiblePanel1") #gets todays incidents panel
#create list call Links
#get all hyperlinks: loads links into Links list while making them full links
Links = [''.join(["http://www.dsfire.gov.uk/News/Newsdesk/",line.get('href')]) for line in incidents.find_all('a')]
#loop through links to find station
incident = ''
for link in Links:
print('Trying {}'.format(link))
webpage = request.urlopen(link) #opens link in list)
soup = BeautifulSoup(webpage) #loads webpage
#check if returned value is found
incident = soup.find_all('p', text=re.compile(r'{}'.format(sStation)))
print(incident)
break
return incident
if __name__ =="__main__":
DSFRSapp().run()
这里有一些重要的注意事项:
- 你提到想把这个打包成安卓应用,但你似乎在用Python3的语法。根据我所知,目前kivy只支持在Python2下运行安卓应用。
- 我建议至少要有一些基本的错误处理,比如在网页解析时没有处理异常。
- 你用来收集事件的网站已经有了xml数据源。直接解析这个数据源会更好,可以更方便地获取事件列表。
- kivy语言在创建复杂的图形界面配置方面要好得多。我建议把kv字符串中的所有内容移到一个名为DSFR.kv的单独文件中。这样你就可以删除Builder.loadstring这一行了。这也会让你更容易进行你在问题中提到的额外修改。
- 我不建议直接把下拉框和网页查询绑定在一起,因为如果网页请求花费的时间太长,程序会卡住。我建议使用一个屏幕管理器,设置一个单独的结果屏幕,并通过下拉框来触发切换。
- 连续向一个网站发送多个查询请求可能会导致你的应用或IP地址被网站管理员列入黑名单。请小心处理这个问题。
额外问题:
- 添加网页链接:非常勤奋的kivy开发者已经为标签类型添加了标记功能。你可以在kivy文档中找到详细信息这里。还有一个示例在这里: Kivy文件中的超链接 但你需要修改它,以便在代码中打开传递给on_ref_press处理程序的引用: 当我在kivy标签中有多个引用时,如何获取引用文本?
- 细红边框:也许这个问题是指你想要的效果:有没有简单的方法给Kivy标签、按钮、控件等添加边框,而不使用图片?