使用BeautifulSoup循环浏览HTML标签
正如前面的问题所述,我使用美丽的汤与python从网站检索天气数据。使用BeautifulSoup循环浏览HTML标签
下面是该网站的样子:
<channel>
<title>2 Hour Forecast</title>
<source>Meteorological Services Singapore</source>
<description>2 Hour Forecast</description>
<item>
<title>Nowcast Table</title>
<category>Singapore Weather Conditions</category>
<forecastIssue date="18-07-2016" time="03:30 PM"/>
<validTime>3.30 pm to 5.30 pm</validTime>
<weatherForecast>
<area forecast="TL" lat="1.37500000" lon="103.83900000" name="Ang Mo Kio"/>
<area forecast="SH" lat="1.32100000" lon="103.92400000" name="Bedok"/>
<area forecast="TL" lat="1.35077200" lon="103.83900000" name="Bishan"/>
<area forecast="CL" lat="1.30400000" lon="103.70100000" name="Boon Lay"/>
<area forecast="CL" lat="1.35300000" lon="103.75400000" name="Bukit Batok"/>
<area forecast="CL" lat="1.27700000" lon="103.81900000" name="Bukit Merah"/>`
..
..
<area forecast="PC" lat="1.41800000" lon="103.83900000" name="Yishun"/>
<channel>
我设法找回我需要使用这些代码的信息:
import requests
from bs4 import BeautifulSoup
import urllib3
import csv
import sys
import json
#getting the Validtime
area_attrs_li = []
r = requests.get('http://www.nea.gov.sg/api/WebAPI/?
dataset=2hr_nowcast&keyref=781CF461BB6606AD907750DFD1D07667C6E7C5141804F45D')
soup = BeautifulSoup(r.content, "xml")
time = soup.find('validTime').string
print "validTime: " + time
#getting the date
for currentdate in soup.find_all('item'):
element = currentdate.find('forecastIssue')
print "date: " + element['date']
#getting the time
for currentdate in soup.find_all('item'):
element = currentdate.find('forecastIssue')
print "time: " + element['time']
#print area
for area in soup.select('area'):
area_attrs_li.append(area)
print area
#print area name
areas = soup.select('area')
for data in areas:
name = (data.get('name'))
print name
f = open("C:\\scripts\\testing\\testingnea.csv" , 'wt')
try:
for area in area_attrs_li:
#print str(area) + "\n"
writer = csv.writer(f)
writer.writerow((time, element['date'], element['time'], area, name))
finally:
f.close()
print open("C:/scripts/testing/testingnea.csv", 'rt').read()
我设法在一个CSV数据,但是当我运行这部分代码:
#print area name
areas = soup.select('area')
for data in areas:
name = (data.get('name'))
print name
这是结果:
很显然,我的回路不工作,因为它保持了一遍又一遍打印的最后一个记录的最后一个领域。
编辑:我想从数据列表中的区域循环:
for area in area_attrs_li:
name = (area.get('name'))
print name
但是,它仍然没有循环。
我不知道在哪里的代码出错:/
这是因为当你写,你是指循环的最后一个实例,试试这个:
writer.writerow((time, element['date'], element['time'], area, area['name']))
的问题是在该行:writer.writerow((time, element['date'], element['time'], area, name))
,在name
永远不会改变。
办法解决它:
try:
for index, area in enumerate(area_attrs_li):
# print str(area) + "\n"
writer = csv.writer(f)
writer.writerow((time, element['date'], element['time'], area, areas[index].get('name')))
finally:
f.close()
你是什么意思的名字永远不会改变的意思吗? :x – plzhelpmi
你只得到了循环后名称变量中的一个值。你需要有一个列表。试试这个
areas = soup.select('area')
name=[]
for data in areas:
name.append(data.get('name'))
print name
l=len(name)
,并尝试终于
i=0
try:
for area in area_attrs_li:
writer = csv.writer(f)
writer.writerow((time, element['date'], element['time'], area, name[i]))
i=i+1
噢,所以我必须创建一个列表,就像我创建一个存储区域一样? – plzhelpmi
是的,你是一次又一次地写同一个值的变量,这就是为什么你总是得到最后一次输入的原因。 –
我不明白你的意思,“当你正在写作时,你指的是循环的最后一个实例”对不起! :/ – plzhelpmi
当你写作时(writer.writerow((time,element ['date'],element ['time'],area,name))),name变量在区域名称循环后保存最后一个值,可以事实上删除>> area_attrs_li中的区域: name =(area.get('name')) 打印名称,虽然它也可以工作,但实践中您可以尝试删除该循环也可以 –
我可以问为什么当它我把它称为循环的最后一个实例的名称,但是当我放置区域时,它工作得很好吗? – plzhelpmi