找一个网页,例如https://www.python.org/events/python-events/,用浏览器查看源码并复制,然后尝试解析一下HTML,输出Python官网发布的会议时间、名称和地点。
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): #首元素
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
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