iT邦幫忙

1

Python 異常訊息 FileNotFoundError

  • 分享至 

  • xImage

錯誤訊息

File "D:/readweather.py", line 15, in parse_html
    with open(arg,'r',encoding='utf-8') as f:

FileNotFoundError: [Errno 2] No such file or directory: 'HTML_DATA\\2018-01-01_466910.htm'

https://ithelp.ithome.com.tw/upload/images/20190910/20119742vZ8Cg5kZEd.png

https://ithelp.ithome.com.tw/upload/images/20190910/20119742TQc4lC4sAm.png

import datetime as dt
import re

#######################################################################
#自訂函式區

def parse_html(arg):
	with open(arg,'r',encoding='utf-8') as f:
		content=f.read()
	f.close()
	content=content.replace('    ','').replace('  ','').replace('\t','').replace('\n','').replace(' ','')
	hours_data=re.findall('<tr><td nowrap>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td></tr>', content)
	return hours_data

看更多先前的討論...收起先前的討論...
dragonH iT邦超人 5 級 ‧ 2019-09-10 13:11:20 檢舉
重點在你怎麼調用 parse_html() 這個 function 的

arg 傳進去是什麼

錯誤訊息已經說得很詳細了

No such file or directory

沒有這個檔案或者資料夾

請善用 google
用絕對資料夾而不要用相對資料夾,或執行時切換到目標資料夾

你無法確定執行時的資料夾到底在哪裡
open(r'C:\windows\abc.txt','rt') 叫絕對資料夾名稱
open(r'...\windows\abc.txt','rt') 叫相對資料夾名稱
ccutmis iT邦高手 2 級 ‧ 2019-09-10 14:58:44 檢舉
樓主你是不是根本沒有抓取'2018-01-01'開頭的html資料?,
上面的附圖裡面只有2018-08-01開頭的htm資料,
先前給你參考的範例檔1_get_weather_htm_data.py
裡面有兩行是用來設定要抓的資料日期
startdate = dt.datetime(2019, 8,1)
enddate = dt.datetime(2019, 8,1)
你如果要抓2018-01-01的資料,那在這邊就要改成
startdate = dt.datetime(2018, 1,1)
enddate = dt.datetime(2018, 1,1)
,然後跑程式就會抓到相對應日期的資料,
我在猜你現在的問題大概就是1.py 的日期是2019,8,1
然後 2.py(讀htm轉csv)的日期是2018,1,1
dragonH iT邦超人 5 級 ‧ 2019-09-10 15:01:33 檢舉
難怪有 2018-01-01 這種日期 XD
ccutmis iT邦高手 2 級 ‧ 2019-09-10 15:03:14 檢舉
樓主目前最需要的應該是Python基礎班
大家是認真的嗎? 只是換個語言來問而已,每次問題都一樣
ccutmis iT邦高手 2 級 ‧ 2019-09-10 15:15:48 檢舉
其實我覺得這位樓主蠻認真的,只是很像初心者。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

3
froce
iT邦大師 1 級 ‧ 2019-09-10 13:32:32
最佳解答

學著看debug訊息啊。python的很詳細。
哪天真的要我寫一本語言的書,一定把錯誤訊息放在前幾章。XD
FileNotFoundError就是找不到你要開的檔案。

因為你寫的是相對目錄,你必須先知道你目前的工作目錄在哪。
不知道你是如何執行py檔的。
如果是利用絕對目錄執行,那就要去看你工作目錄。

c:\users\aaa>python d:\webCrawler\xxx.py

這樣的話,你的py檔會去讀 c:\users\aaa\HTML_DATA\2018-01-01_466910.htm
而不是 d:\webCrawler\HTML_DATA\2018-01-01_466910.htm

另外補充一招,通常我都會把他轉成絕對目錄處理。

import os

pyDir = os.path.dirname(os.path.absname(__file__))
with open(os.path.join(pyDir, "HTML_DATA\\2018-01-01_466910.htm"), "r") as f:
    pass
看更多先前的回應...收起先前的回應...
ccutmis iT邦高手 2 級 ‧ 2019-09-10 14:12:43 檢舉

斯斯有兩種,
File no found 也有兩種 一種是路徑問題 另一種就是檔案真的不在該資料夾裡...
/images/emoticon/emoticon77.gif

dragonH iT邦超人 5 級 ‧ 2019-09-10 14:17:10 檢舉

根據我過人的眼力

他應該是第二種 /images/emoticon/emoticon39.gif

2018-01-01_466910.htm
ccutmis iT邦高手 2 級 ‧ 2019-09-10 14:43:01 檢舉

https://media.tenor.com/images/027af2c70a60536a7d311e8b084a9ae7/tenor.gif

kevin543 iT邦新手 5 級 ‧ 2019-09-10 15:04:07 檢舉

我知道錯誤訊息 FileNotFoundError 就是找不到你要開的檔案 , 所以我把檔案目錄貼上來 , 不是就在 D:\HTML_DATA\ 下面 , 是指定相對目錄設定錯誤 ?
https://ithelp.ithome.com.tw/upload/images/20190910/20119742CtWpXJMGbX.png

我的 PY 是這樣執行的 , 先執行下面

import datetime as dt #將函數 datetime 指定給 dt
import requests,time,pathlib,os,re #輸入需要的函數

#######################################################################
#自訂函式區
def get_url_filename(arg): # 取得網頁檔案 arg能夠接收不定量的非關鍵字參數
	return re.sub(r'^.*?station=(.*?)&stname=&datepicker=(.*?)$',r'\2_\1',arg)
  #re.sub屬於python正則的標準庫,主要是的功能是用正則匹配要替換的字串
def log(arg): # log函數是代表記錄的log 
	with open('log\\event.log','a',encoding='utf-8') as f: #打開event.log 'a'新的內容將會被寫入到已有內容之後。如果該文件不存在,創建新文件進行寫入。 utf-8 中文編碼
		f.writelines(arg+'\n') # f=file 寫入行並換行 
	f.close() # 關檔

#######################################################################

base_dir = os.path.dirname(os.path.realpath(__file__))
#判斷log資料夾是否存在,若不存在則建立log資料夾
pathlib.Path(base_dir+"\\log\\").mkdir(parents=True, exist_ok=True)

with open('log\\event.log','w',encoding='utf-8') as f: #把open那邊傳回來的值存入f這個變數
	pass #這裡用意是把event.log內容清空
f.close()

location_dict={'466910':'鞍部','466920':'臺北','466930':'竹子湖','C0A980':'社子','C0A9A0':'大直','C0A9B0':'石牌','C0A9C0':'天母','C0A9E0':'士林','C0A9F0':'內湖','C0AC40':'大屯山','C0AC70':'信義','C0AC80':'文山','C0AH40':'平等','C0AH70':'松山','C1AC50':'關渡','C1A730':'公館','C0A9G0':'南港','C0A990':'大崙尾山'}
#print(location_dict.keys()) 測試列出location_dict所有key:466910,466920...

#下載日期起點終點
startdate = dt.datetime(2019, 8,1)
enddate = dt.datetime(2019, 8,1)
totaldate = (enddate - startdate).days + 1

data_folder='HTML_DATA'
#判斷HTML_DATA資料夾是否存在,若不存在則建立HTML_DATA資料夾
pathlib.Path(data_folder).mkdir(parents=True, exist_ok=True)

#######################################################################
#下載全部html資料到HTML_DATA資料夾
for daynumber in range(totaldate): # 迴圈 日期數目在全部日期的範圍內
	datestring = str((startdate + dt.timedelta(days = daynumber)).date())
    #將日期轉換為字串
	print(datestring)
	#取得單日_全部地點.htm
	for i in location_dict.keys(): # 迴圈 i 從監測站起點到終點下載資料
		url="https://e-service.cwb.gov.tw/HistoryDataQuery/DayDataController.do?command=viewMain&station=%s&stname=&datepicker=%s" %(i.split("_")[0],datestring)
		#print(url)
		try: #異常狀況處裡 ,避免當機產生
			r=requests.get(url) ## 使用 GET 方式下載普通網頁
			print("Download: "+datestring+"_"+i+".htm") #列印下載日期 , 當 i 迴圈中斷的地方
			with open(data_folder+"\\"+datestring+"_"+i+".htm",'w',encoding='utf-8') as f:
                #打開檔案目錄與日期在 i 迴圈
				f.write(r.text) #寫入 r.text 檔案
			f.close() # 關閉
		except:
			print("Error: "+datestring+"_"+i+".htm")
			#列印錯誤日期在迴圈 i 的何處停止
			log(url)
		finally:
			time.sleep(5)
print("1. HTML資料下載完畢.")

#######################################################################
#檢查event.log是否為空或有內容,有則表示有資料下載失敗需要重新下載
log_file = (open("log\\event.log", "r"))
download_error_url = log_file.read().split('\n')
log_file.close()
#若download_error_url陣列長度為1時表示是沒有錯誤(只有一列空白行)
#大於1表示有下載錯誤的記錄
if (len(download_error_url))>1:  #假如下載錯誤網址長度>1
	with open('log\\event.log','w',encoding='utf-8') as f:
		pass #這裡用意是把event.log內容清空
	f.close()
	for i in download_error_url: # 迴圈 i 在 下載錯誤網址
		if i!='': #假如 i 不等於空白
			try: # 異常處理同上
				r=requests.get(i)
				print("Download: "+get_url_filename(i)+".htm")
				with open(data_folder+"\\"+get_url_filename(i)+".htm",'w',encoding='utf-8') as f:
					f.write(r.text)
				f.close()
			except:
				print("Error: "+get_url_filename(i)+".htm")
				log(i)
			finally:
				time.sleep(5)
	print("2. 下載錯誤HTML資料補下載完畢.")
else:
	print("2. 檢查完畢,無下載錯誤HTML資料.")

再執行下面

import datetime as dt
import re

#######################################################################
#自訂函式區

def parse_html(arg):
	with open(arg,'r',encoding='utf-8') as f:
		content=f.read()
	f.close()
	content=content.replace('    ','').replace('  ','').replace('\t','').replace('\n','').replace('&nbsp;','')
	hours_data=re.findall('<tr><td nowrap>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td><td>([^<]+)</td></tr>', content)
	return hours_data

#######################################################################

location_dict={'466910':'鞍部','466920':'臺北','466930':'竹子湖','C0A980':'社子','C0A9A0':'大直','C0A9B0':'石牌','C0A9C0':'天母','C0A9E0':'士林','C0A9F0':'內湖','C0AC40':'大屯山','C0AC70':'信義','C0AC80':'文山','C0AH40':'平等','C0AH70':'松山','C1AC50':'關渡','C1A730':'公館','C0A9G0':'南港','C0A990':'大崙尾山'}
#print(location_dict.keys()) 測試列出location_dict所有key:466910,466920...

startdate = dt.datetime(2018, 1,1)
enddate = dt.datetime(2018, 1,2)
totaldate = (enddate - startdate).days + 1

data_folder='HTML_DATA'

#######################################################################
#讀取HTML_DATA資料夾內全部html文件,解析HTML源碼後存為weather.csv

with open('weather.csv','w',encoding='utf-8') as f:
	f.writelines('Station,ObsTime,StnPres,SeaPres,Temperature,Td dew point,RH,WS,WD,WSGust,WDGust,Precp,PrecpHour,SunShine,GloblRad,Visb,UVI,Cloud Amount\n')
	for daynumber in range(totaldate):
		datestring = str((startdate + dt.timedelta(days = daynumber)).date())
		#print(datestring)
		#取得單日_全部地點.htm
		for i in location_dict.keys():
			print(datestring+str(i))
			hours_arr=parse_html(data_folder+"\\"+datestring+"_"+i+".htm")
			for j in hours_arr:
				print("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n"%(i,datestring+' '+j[0]+':00:00',j[1],j[2],j[3],j[4],j[5],j[6],j[7],j[8],j[9],j[10],j[11],j[12],j[13],j[14],j[15],j[16]))
				#f.writelines("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n"%(location_dict[i],datestring+' '+(j[0] if j[0]!='24' else '00')+':00:00',j[1],j[2],j[3],j[4],j[5],j[6],j[7],j[8],j[9],j[10],j[11],j[12],j[13],j[14],j[15],j[16]))
				f.writelines("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n"%(i,datestring+' '+(j[0] if j[0]!='24' else '00')+':00:00',j[1],j[2],j[3],j[4],j[5],j[6],j[7],j[8],j[9],j[10],j[11],j[12],j[13],j[14],j[15],j[16]))
f.close()
ccutmis iT邦高手 2 級 ‧ 2019-09-10 15:10:13 檢舉

你有發現1.py跟2.py兩個的日期設定不一樣嗎,你抓htm設2019,8,1~2019,8,1,讀htm設2018,1,1~2018,1,2,這樣怎會不出錯?

把1.py的日期設2018,1,1~2018,1,2,存檔再重跑一遍1.py 2.py看看,應該就OK了

kevin543 iT邦新手 5 級 ‧ 2019-09-10 15:12:18 檢舉

謝謝 ! 發現了 , 可以執行了

ccutmis iT邦高手 2 級 ‧ 2019-09-10 15:16:34 檢舉

GOOD JOB~ /images/emoticon/emoticon30.gif

kevin543 iT邦新手 5 級 ‧ 2019-09-10 15:37:48 檢舉

我換了這行 , 應該變中文 , 怎麼變亂碼 , 主要是 location_dict[i] 的差別

f.writelines("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n"%(location_dict[i],datestring+' '+(j[0] if j[0]!='24' else '00')+':00:00',j[1],j[2],j[3],j[4],j[5],j[6],j[7],j[8],j[9],j[10],j[11],j[12],j[13],j[14],j[15],j[16]))

https://ithelp.ithome.com.tw/upload/images/20190910/20119742nJUlkkFsAB.png

kevin543 iT邦新手 5 級 ‧ 2019-09-10 15:40:45 檢舉

我的程度只有 99 乘法與判斷數字大小 , 接近百行的程式 , 還要慢慢加強才行

froce iT邦大師 1 級 ‧ 2019-09-10 15:43:06 檢舉

所以說你不要急於寫爬蟲啊,先練基本工,要不然你根本不懂你寫的是什麼,你要怎麼寫?
先把你每一行程式碼在寫什麼,為什麼要傳這些參數,裡面用到的函數接收什麼參數,吐出什麼參數搞清楚。

寫程式就像演講一樣,一個語言你連詞彙都還不會,你要怎麼做一場精彩的演講?

kevin543 iT邦新手 5 級 ‧ 2019-09-10 15:53:44 檢舉

因為我們小組要交專題 9/24 就結業了 , 所以要寫爬蟲抓資料分析 , 我們小組有 6 個人 , 一個以前寫過 C , 他比較會寫 , 但也不能只靠他一個人 , 所以我們要分擔工作 , 我就寫爬蟲從中在學

ccutmis iT邦高手 2 級 ‧ 2019-09-10 16:11:27 檢舉

kevin543
有個鐵人賽作者 心原一馬 他的Python超入門全部篇章推薦你完整一字不露的看個十遍,然後把範例自己keyin十遍執行看看,應該會對基礎有幫助。

【Python 超入門】(1) 心原一馬從零開始帶你學程式
https://ithelp.ithome.com.tw/articles/10211960

froce iT邦大師 1 級 ‧ 2019-09-10 16:29:03 檢舉

好奇你們的專題是什麼?
爬蟲+web弄個資訊站這樣?

kevin543 iT邦新手 5 級 ‧ 2019-09-10 16:45:42 檢舉

UBIKE 使用特性資料分析 , 包括使用率 熱冷門站點 熱門路線 平日假日租借分析 雨天租借使用率.... 等等

froce iT邦大師 1 級 ‧ 2019-09-10 17:01:56 檢舉

如果工作還沒分配下去的話,我會建議:
爬蟲請會寫c語言的寫,你們不會的寫那些統計功能。

python因為內建函式庫比較齊全,要寫那些功能比爬蟲容易,也可以順便練習語法和寫程式的感覺

如果不要介面的話,你們的專題聽起來還蠻簡單的,難度應該不會太過。
說嚴厲點,資策會的課程也蠻貴的,去學了卻沒獨力完成的能力的話,真的要檢討一下夠不夠努力了。

kevin543 iT邦新手 5 級 ‧ 2019-09-10 22:58:38 檢舉

謝謝指點 , 資料都抓完了 , 剩下統計功能 , 我們就可以完成了

kevin543 iT邦新手 5 級 ‧ 2019-09-10 23:08:26 檢舉

我們班 34 個人 , 是勞動部失業補助課程 , 女生佔一半 , 會寫的幾乎都是男生 , 也都是之前有寫過的 , 沒寫過上課後會寫的很少 , 同學也都很認真 , 少數幾個屁孩打混外 , 其他上課都常發問 , EXCEL 函數分析大家都比較熟 , 程式強的就不多

我要發表回答

立即登入回答