PythonD11——常用内建(itertools contextlib urllib XML HTMLParser)

编程入门 行业动态 更新时间:2024-10-09 14:19:51

PythonD11——常用<a href=https://www.elefans.com/category/jswz/34/1765782.html style=内建(itertools contextlib urllib XML HTMLParser)"/>

PythonD11——常用内建(itertools contextlib urllib XML HTMLParser)

文章目录

  • 常用内建函数(续)
    • itertools操作迭代对象
    • 一些常用迭代操作函数
      • chain()串联作用
      • groupby()
      • 作业:计算π
    • contextlib操作文件资源
    • urllib操纵url
    • XML类似json
    • HTMLParser

常用内建函数(续)

itertools操作迭代对象

import itertools
#无限打印自然数
natuals = itertools.count(1)
for n in natuals:print(n)
#无限打印输入序列
cs = itertools.cycle('ABC') # 注意字符串也是序列的一种
for c in cs:print(c)
#指定打印三次
ns = itertools.repeat('A', 3)
for n in ns:print(n)
#使用takewhile来限定范围
natuals = itertools.count(1)
ns = itertools.takewhile(lambda x: x <= 10, natuals)
list(ns)

一些常用迭代操作函数

chain()串联作用

chain()可以把一组迭代对象串联起来,形成一个更大的迭代器

groupby()

groupby()把迭代器中相邻的重复元素挑出来放在一起,可以消除重复元素。

for key, group in itertools.groupby('AaaBBbcCAAa', lambda c: c.upper()):print(key, list(group))
...
A ['A', 'a', 'a']
B ['B', 'B', 'b']
C ['c', 'C']
A ['A', 'A', 'a']

作业:计算π

def pi(N):' 计算pi的值 '# step 1: 创建一个奇数序列: 1, 3, 5, 7, 9, ...qi = itertools.count(1,2)# step 2: 取该序列的前N项: 1, 3, 5, 7, 9, ..., 2*N-1.qu = itertools.takewhile(lambda x:x<=2*N-1,qi)# step 3: 添加正负符号并用4除: 4/1, -4/3, 4/5, -4/7, 4/9, ...qu_list = [4/x*(-1)**(idx%2) for idx,x in enumerate(list(qu))]#step3第二种qu_list = [4/x*(-1)**((x+1)/2-1) for x in qu]# step 4: 求和:return sum(qu_list)

contextlib操作文件资源

主要是通过with作为一个上下文管理器。

@contextmanager
def transaction(db):db.begin()try:yield except:db.rollback()raiseelse:dbmit()
with transaction(mydb):mydb.cursor.execute(sql)mydb.cursor.execute(sql)mydb.cursor.execute(sql)mydb.cursor.execute(sql)

with执行过程:
执行 context_expression,生成上下文管理器 context_manager

调用上下文管理器的__enter__() 方法;如果使用了 as 子句,则将__enter__() 方法的返回值赋值给 as 子句中的 target(s)

执行语句体 with-body

不管是否执行过程中是否发生了异常,执行上下文管理器的__exit__() 方法__exit__() 方法负责执行“清理”工作,如释放资源等。如果执行过程中没有出现异常,或者语句体中执行了语句 break/continue/return,则以 None 作为参数调用__exit__(None, None, None) ;如果执行过程中出现异常,则使用 sys.exc_info 得到的异常信息为参数调用__exit__(exc_type, exc_value, exc_traceback)

出现异常时,如果__exit__(type, value, traceback) 返回 False,则会重新抛出异常,让with 之外的语句逻辑来处理异常,这也是通用做法;如果返回 True,则忽略异常,不再对异常进行处理

.html?mhsrc=ibmsearch_a&mhq=%E4%B8%8A%E4%B8%8B%E6%96%87%20Python
本体.html

urllib操纵url

urllib提供的功能就是利用程序去执行各种HTTP请求。

如果要模拟浏览器完成特定功能,需要把请求伪装成浏览器。

伪装的方法是先监控浏览器发出的请求,再根据浏览器的请求头来伪装,User-Agent头就是用来标识浏览器的。

from urllib import requestreq = request.Request('/')
req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')
with request.urlopen(req) as f:print('Status:', f.status, f.reason)for k, v in f.getheaders():print('%s: %s' % (k, v))print('Data:', f.read().decode('utf-8'))

更复杂的可以通过post和handle去访问。

作业:解析url json并转换

from urllib import request
import json
def fetch_data(url):with request.urlopen(str(url)) as f:return json.loads(f.read().decode('utf-8'))return None

XML类似json

操作XML有两种方法:DOM和SAX。DOM会把整个XML读入内存,解析为树,因此占用内存大,解析慢,优点是可以任意遍历树的节点。SAX是流模式,边读边解析,占用内存小,解析快,缺点是我们需要自己处理事件。

champhy_hu大佬的实例

from xml.parsers.expat import ParserCreate
#利用SAX解析XML文档牵涉到两个部分: 解析器和事件处理器
#解析器负责读取XML文档,并向事件处理器发送事件,如元素开始跟元素结束事件。
#而事件处理器则负责对事件作出响应,对传递的XML数据进行处理class DefualtSaxHandler(object):def start_element(self,name,attrs):print('sax:start_elment: %s,attrs: %s'%(name,str(attrs)))#name表示节点名称,attrs表示节点属性(字典)def end_element(self,name):print('sax:end_element: %s'%name)def char_data(self,text):print('sax:char_data: %s'%text)#text表示节点数据
xml=r'''<?xml version="1.0"?>
<ol><li><a href="/python">Python</a></li><li><a href="/ruby">Ruby</a></li>
</ol>
'''#处理器实例
handler=DefualtSaxHandler()
#解析器实例
parser=ParserCreate()#下面3为解析器设置自定义的回调函数
#回调函数的概念,请搜索知乎,见1.9K赞的答案
parser.StartElementHandler=handler.start_element
parser.EndElementHandler=handler.end_element
parser.CharacterDataHandler=handler.char_data
#开始解析XML
parser.Parse(xml)
#然后就是等待expat解析,
#一旦expat解析器遇到xml的 元素开始,元素结束,元素值 事件时
#会回分别调用start_element, end_element, char_data函数#关于XMLParser Objects的方法介绍下
#详见python文档:xml.parsers.expat
#xmlparser.StartElementHandler(name, attributes)
#遇到XML开始标签时调用,name是标签的名字,attrs是标签的属性值字典
#xmlparser.EndElementHandler(name)
#遇到XML结束标签时调用。
#xmlparser.CharacterDataHandler(data) 
#调用时机:
#从行开始,遇到标签之前,存在字符,content 的值为这些字符串。
#从一个标签,遇到下一个标签之前, 存在字符,content 的值为这些字符串。
#从一个标签,遇到行结束符之前,存在字符,content 的值为这些字符串。
#标签可以是开始标签,也可以是结束标签。#为了方便理解,我已经在下面还原来解析过程,
#标出何时调用,分别用S:表示开始;E:表示结束;D:表示data如果看不明白,请配合脚本输出结果一起看
S<ol>C
C   S<li>S<a href="/python">CPython</a>E</li>EC
C   S<li>S<a href="/ruby">CRuby</a>E</li>EC
S</ol>E

作业:写一个可以输出天气的api

'''练习:
请利用SAX编写程序解析XML格式的天气预报,获取天气预报:功能:获取北京市所有地区的当天天气预报信息——(地区名:{当日天气状态:’‘,最高温度:’‘,最低温度})
'''
# -*- coding:utf-8 -*-from xml.parsers.expat import ParserCreate            # 引入xml解析模块
from urllib import request                            # 引入URL请求模块class WeatherSaxHandler(object):                      # 定义一个天气事件处理器weather ={'city':1,'cityname':[], 'forecast':[]}               # 初始化城市city和预报信息forecastdef start_element(self, name, attrs):             # 定义开始标签处理事件if name=='beijing':self.weather['city']='北京'if name == 'city':               # 获取location信息self.weather['cityname'].append(attrs['cityname'])          #获取地区名# 获取forecast信息self.weather['forecast'].append({'state':attrs['stateDetailed'], 'high':attrs['tem2'], 'low':attrs['tem1']})def parseXml(xml_str):                                # 定义xml解析器handler = WeatherSaxHandler()parser = ParserCreate()parser.StartElementHandler = handler.start_elementparser.Parse(xml_str)                             # 解析xml文本print('City'+handler.weather['city'])for (x,y) in zip(handler.weather['cityname'],handler.weather['forecast']):             # 打印天气信息print('Region:'+x)print(y)return handler.weather# 测试:
URL = '.xml'with request.urlopen(URL, timeout=4) as f:data = f.read()result = parseXml(data.decode('utf-8'))'''结果
City北京
Region:延庆
{'state': '晴', 'high': '7', 'low': '-7'}
Region:密云
{'state': '晴', 'high': '9', 'low': '-6'}
Region:怀柔
{'state': '晴', 'high': '10', 'low': '-6'}
Region:昌平
{'state': '晴', 'high': '9', 'low': '-1'}
Region:平谷
{'state': '晴', 'high': '8', 'low': '-5'}
Region:顺义
{'state': '晴', 'high': '10', 'low': '0'}
Region:门头沟
{'state': '晴', 'high': '10', 'low': '-2'}
Region:海淀
{'state': '晴', 'high': '11', 'low': '-2'}
Region:朝阳
{'state': '晴', 'high': '10', 'low': '-1'}
Region:石景山
{'state': '晴', 'high': '11', 'low': '-2'}
Region:市中心
{'state': '晴', 'high': '9', 'low': '-2'}
Region:丰台
{'state': '晴', 'high': '10', 'low': '-2'}
Region:房山
{'state': '晴', 'high': '9', 'low': '-4'}
Region:大兴
{'state': '晴', 'high': '9', 'low': '-4'}
Region:通州
{'state': '晴', 'high': '9', 'low': '-2'}
'''

HTMLParser

如果我们要编写一个搜索引擎,第一步是用爬虫把目标网站的页面抓下来,第二步就是解析该HTML页面,看看里面的内容到底是新闻、图片还是视频。

解析HTML就要用到HTMLParser

# -*-coding:UTF-8-*-from html.parser import HTMLParser
from urllib.request import Request,urlopen
import redef 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 = '/'data = get_data(URL)parser.feed(data)for s in parser.info:print(s)if __name__ == '__main__':main()
#第二种
from html.parser import HTMLParser
from urllib import requestclass MyHTMLParser(HTMLParser):def __init__(self):super().__init__()self.flag = 0  # 状态 1:目标标签 0:不是目标标签def handle_starttag(self, tag, attrs):if tag == 'h3' and ('class', 'event-title') in attrs:  # 筛选会议名称self.flag = 1elif tag == 'time' and 'datetime' in attrs[0]:  # 筛选会议时间self.flag = 1elif tag == 'span' and ('class', 'event-location') in attrs:  # 筛选会议地点self.flag = 1def handle_data(self, data):if self.flag:print(data)self.flag = 0  # 还原状态with request.urlopen('/') as f:data = f.read().decode('utf-8')parser = MyHTMLParser()
parser.feed(data)

更多推荐

PythonD11——常用内建(itertools contextlib urllib XML HTMLParser)

本文发布于:2024-03-05 11:54:27,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1712226.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:内建   常用   itertools   XML   HTMLParser

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!