使用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 

这是结果:

This is what I got

很显然,我的回路不工作,因为它保持了一遍又一遍打印的最后一个记录的最后一个领域。

编辑:我想从数据列表中的区域循环:

for area in area_attrs_li: 
    name = (area.get('name')) 
    print name 

但是,它仍然没有循环。

我不知道在哪里的代码出错:/

这是因为当你写,你是指循环的最后一个实例,试试这个:

writer.writerow((time, element['date'], element['time'], area, area['name'])) 
+0

我不明白你的意思,“当你正在写作时,你指的是循环的最后一个实例”对不起! :/ – plzhelpmi

+0

当你写作时(writer.writerow((time,element ['date'],element ['time'],area,name))),name变量在区域名称循环后保存最后一个值,可以事实上删除>> area_attrs_li中的区域: name =(area.get('name')) 打印名称,虽然它也可以工作,但实践中您可以尝试删除该循环也可以 –

+0

我可以问为什么当它我把它称为循环的最后一个实例的名称,但是当我放置区域时,它工作得很好吗? – plzhelpmi

的问题是在该行: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() 
+0

你是什么意思的名字永远不会改变的意思吗? :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 
+0

噢,所以我必须创建一个列表,就像我创建一个存储区域一样? – plzhelpmi

+0

是的,你是一次又一次地写同一个值的变量,这就是为什么你总是得到最后一次输入的原因。 –