題目
找一個網頁,例如https://www.python.org/events/python-events/,用瀏覽器查看源碼並複製,然後嘗試解析一下HTML,輸出Python官網發佈的會議時間、名稱和地點。
代碼版本1——時區轉換
from html.parser import HTMLParser
from urllib import request
from datetime import datetime
from pytz import utc
from pytz import timezone
class EventSearchParser(HTMLParser):
def __init__(self):
super().__init__()
self.Cons=[]
self.times=[]
self.locs=[]
self.__Conference=' ' #標誌位(conference和location)
def handle_starttag(self, tag, attrs): #首元素 <start>
attrs=dict(attrs)
if tag=='h3' and 'class' in attrs:
if attrs['class']=='event-title': #判斷爲事件,其字段數據爲會議名字
self.__Conference='conference'
if tag=='time' and 'datetime' in attrs: #判斷爲日期
cst_tz = timezone('Asia/Shanghai') #上海時區
utc_tz = timezone('UTC') #UTC
dt=datetime.strptime(attrs['datetime'][:-6],'%Y-%m-%dT%H:%M:%S') #str->datetime
dt_utc=dt.replace(tzinfo=utc_tz) #添加時區0:00
dt_Shanghai=dt_utc.astimezone(cst_tz) #轉換爲上海時區
self.times.append(dt_Shanghai)
if tag=='span' and 'class' in attrs:
if attrs['class']=='event-location': #判斷爲地點,其字段數據爲地點
self.__Conference='location'
def handle_data(self, data): #字段數據
if self.__Conference=='conference':
self.Cons.append(data)
if self.__Conference=='location':
self.locs.append(data)
def handle_endtag(self,tag): #結束標籤時清空
self.__Conference=' '
def url2html(url):
header={
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36'}
req=request.Request(url,headers=header)
with request.urlopen(req,timeout=25) as f:
print(f'Status:{f.status} {f.reason} \n') #狀態碼和對應狀態
html=f.read().decode(encoding='utf_8') #bytes->str
return html
def output(parser):
i=1
for x,y,z in zip(parser.Cons,parser.times,parser.locs):
print('第%d個會議\nConferencesName:%s\nDate:%s\nLocation:%s\n'%(i,x,y,z))
i+=1
def main():
parser=EventSearchParser()
url='https://www.python.org/events/python-events/'
htmlsource=url2html(url)
parser.feed(htmlsource)
output(parser)
if __name__=='__main__':
main()
運行結果
Status:200 OK
第1個會議
ConferencesName:HackBVICAM National Student’s Convention 2k20
Date:2020-03-13 08:00:00+08:00
Location:New Delhi, India
第2個會議
ConferencesName:MoscowPythonConf++
Date:2020-03-27 08:00:00+08:00
Location:Moscow, Russia
第3個會議
ConferencesName:PyCon SK 2020
Date:2020-03-27 08:00:00+08:00
Location:Bratislava, Slovakia
第4個會議
ConferencesName:PyCon Italia 2020
Date:2020-04-02 08:00:00+08:00
Location:Florence, Italy
第5個會議
ConferencesName:PyCon US 2020
Date:2020-04-15 08:00:00+08:00
Location:Pittsburgh, PA, USA
第6個會議
ConferencesName:Django Day Copenhagen
Date:2020-04-17 08:00:00+08:00
Location:Copenhagen, Denmark
第7個會議
ConferencesName:PyCon Belarus 2020
Date:2020-02-21 08:00:00+08:00
Location:Minsk, Belarus
第8個會議
ConferencesName:Open Source Festival
Date:2020-02-20 08:00:00+08:00
Location:Lagos, Nigeria
代碼版本2(轉載)——正則表達式
from html.parser import HTMLParser
from urllib.request import Request,urlopen
import re
def get_data(url):
'''
GET請求到指定的頁面
:return: HTTP響應
'''
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36'
}
req = Request(url, headers=headers)
with urlopen(req, timeout=25) as f:
data = f.read()
print(f'Status: {f.status} {f.reason}')
print()
return data.decode("utf-8")
class MyHTMLParser(HTMLParser):
def __init__(self):
super().__init__()
self.__parsedata='' # 設置一個空的標誌位
self.info = []
def handle_starttag(self, tag, attrs):
if ('class', 'event-title') in attrs:
self.__parsedata = 'name' # 通過屬性判斷如果該標籤是我們要找的標籤,設置標誌位
if tag == 'time':
self.__parsedata = 'time'
if ('class', 'say-no-more') in attrs:
self.__parsedata = 'year'
if ('class', 'event-location') in attrs:
self.__parsedata = 'location'
def handle_endtag(self, tag):
self.__parsedata = ''# 在HTML 標籤結束時,把標誌位清空
def handle_data(self, data):
if self.__parsedata == 'name':
# 通過標誌位判斷,輸出打印標籤內容
self.info.append(f'會議名稱:{data}')
if self.__parsedata == 'time':
self.info.append(f'會議時間:{data}')
if self.__parsedata == 'year':
if re.match(r'\s\d{4}', data): # 因爲後面還有兩組 say-no-more 後面的data卻不是年份信息,所以用正則檢測一下
self.info.append(f'會議年份:{data.strip()}')
if self.__parsedata == 'location':
self.info.append(f'會議地點:{data} \n')
def main():
parser = MyHTMLParser()
URL = 'https://www.python.org/events/python-events/'
data = get_data(URL)
parser.feed(data)
for s in parser.info:
print(s)
if __name__ == '__main__':
main()
運行結果
Status: 200 OK
會議名稱:PyCon AU 2019
會議時間:02 Aug. – 06 Aug.
會議年份:2019
會議地點:Sydney, Australia
會議名稱:DjangoCon AU 2019
會議時間:02 Aug.
會議年份:2019
會議地點:Sydney, Australia
會議名稱:PyBay
會議時間:15 Aug. – 18 Aug.
會議年份:2019
會議地點:Mission Bay, San Francisco, CA, USA
會議名稱:PyCon Korea 2019
會議時間:15 Aug. – 18 Aug.
會議年份:2019
會議地點:Seoul
會議名稱:Kiwi PyCon X
會議時間:23 Aug. – 25 Aug.
會議年份:2019
會議地點:Wellington, New Zealand