Python3----第十五章 Python和Web

#!usr/bin/env python  
# -*- coding:utf-8 _*-
""" 
@author:AIVision 
@file: lecture15.py 
@time: 2023/09/27 
"""

# 第十五章 Python和Web
# 本章讨论Python Web编程的一些方面。Web编程涉及的范围极广,为激发你的学习兴趣,这
# 里挑选了其中三个重要的主题:屏幕抓取、CGI和mod_python。

# 15.1 屏幕抓取
# 屏幕抓取是通过程序下载网页并从中提取信息的过程。这种技术很有用,在网页中有你要在
# 程序中使用的信息时,就可使用它。当然,如果网页是动态的,即随时间而变化,这就更有用了。
# 如果网页不是动态的,你可手工下载一次并提取其中的信息。(当然,最理想的情况是,可通过
# Web服务来获取这些信息,这将在本章后面讨论。)
# 从概念上说,这种技术非常简单:下载数据并对其进行分析。例如,你可使用urllib来获取
# 网页的HTML代码,再使用正则表达式(参见第10章)或其他技术从中提取信息。例如,假设你
# 要从Python Job Board(http://python.org/jobs)提取招聘单位的名称和网站。通过查看该网页的源
# 代码,你发现可在类似于下面的链接中找到名称和URL:
# Python Engineer
# 代码清单15-1所示的示例程序使用urllib和re来提取所需的信息。

# 代码清单15-1 简单的屏幕抓取程序
from urllib.request import urlopen
import re
p = re.compile('(.*?)')
text = urlopen('http://python.org/jobs').read().decode()
for url, name in p.findall(text):
    print('{} ({})'.format(name, url))

# 15.1.1 Tidy 和 XHTML 解析
# Python标准库为解析HTML和XML等结构化格式提供了强大的支持(参见“Python库参考手
# 册”中的Structured Markup Processing Tools部分)。XML和XML解析将在第22章更深入地讨论,
# 这里只介绍处理XHTML所需的工具。XHTML是HTML 5规范描述的两种具体语法之一,也是一
# 种XML格式。这里介绍的大部分内容也适用于HTML。
# 如果每个网页包含的XHTML都正确而有效,解析工作将非常简单。问题是较老的HTML方
# 言不那么严谨,虽然有人指责这些不严谨的方言,但有些人对这些指责置若罔闻。原因可能在于
# 大多数Web浏览器都非常宽容,即便面对的是最混乱、最无意义的HTML,也会尽最大努力将其
# 渲染出来。这为网页制作者提供了方便,可能让他们感到满意,却让屏幕抓取工作变得难得多。
# 标准库提供的通用的HTML解析方法是基于事件的:你编写事件处理程序,供解析程序处理
# 数据时调用。标准库模块html.parser让你能够以这种方式对极不严谨的HTML进行解析,但要基
# 于文档结构来提取数据(如第二个二级标题后面的第一项),在存在标签缺失的情况下恐怕就只
# 能靠猜了。如果你愿意,当然可以这样做,但还有另一种方式——使用Tidy。

# 1. Tidy是什么
# Tidy是用于对格式不正确且不严谨的HTML进行修复的工具。它非常聪明,能够修复很多常
# 见的错误,从而完成大量你不愿意做的工作。它还提供了极大的配置空间,让你能够开/关各种
# 校正。

# 2. 获取Tidy
# 有多个用于Python的Tidy库包装器,至于哪个最新并非固定不变的。可像下面这样使用pip
# 来找出可供使用的包装器:
# $ pip search tidy
# 一个不错的选择是PyTidyLib,可像下面这样安装它:
# $ pip install pytidylib

# 3. 为何使用XHTML
# XHTML和旧式HTML的主要区别在于,XHTML非常严格,要求显式地结束所有的元素(至
# 少就我们当前的目标而言如此)。因此,在HTML中,可通过(使用标签

)开始另一个段落来 # 结束当前段落,但在XHTML中,必须先(使用标签

)显式地结束当前段落。这让XHTML
# 解析起来容易得多,因为你能清楚地知道何时进入或离开各种元素。XHTML的另一个优点是, # 它是一种XML方言,可使用各种出色的工具(如XPath)来处理,但本章不会利用这一点。有关 # XML的详细信息,请参阅第22章。有关如何使用XPath的详细信息,请参阅http://www.w3schools. # com/xml/xml:xpath.asp。 # 要对Tidy生成的格式良好的XHTML进行解析,一种非常简单的方式是使用标准库模块 # html.parser中的HTMLParser类。 # 4. 使用HTMLParser # 使用HTMLParser意味着继承它,并重写各种事件处理方法,如handle_starttag和handle_data。 # 表15-1概述了相关的方法以及解析器在什么时候自动调用它们。 # 表15-1 HTMLParser中的回调方法 # 回调方法 何时被调用 # handle_starttag(tag, attrs) 遇到开始标签时调用。attrs是一个由形如(name, value)的元组组成的序列 # handle_startendtag(tag, attrs) 遇到空标签时调用。默认分别处理开始标签和结束标签 # handle_endtag(tag) 遇到结束标签时调用 # handle_data(data) 遇到文本数据时调用 # handle_charref(ref) 遇到形如&#ref;的字符引用时调用 # handle_entityref(name) 遇到形如&name;的实体引用时调用 # handle_comment(data) 遇到注释时;只对注释内容调用 # handle_decl(decl) 遇到形如的声明时调用 # handle_pi(data) 用于处理指令 # unknown_decl(data) 遇到未知声明时调用 # 15.2 使用 CGI 创建动态网页 # 本章的第一部分讨论了客户端技术,下面将注意力转向服务器端。本节讨论基本的Web编程 # 技术:通用网关接口(CGI)。CGI是一种标准机制,Web服务器可通过它将(通常是通过Web表 # 达提供的)查询交给专用程序(如你编写的Python程序),并以网页的方式显示查询结果。这是 # 一种创建Web应用的简单方式,让你无需编写专用的应用程序服务器。有关Python CGI编程的详 # 细信息,请参阅Python网站的Web编程主题指南(http://wiki.python.org/moin/WebProgramming)。 # Python CGI编程的关键工具是模块cgi,另一个对开发CGI脚本很有帮助的模块是cgitb,将 # 在15.2.6节详细介绍。 # 要让CGI脚本能够通过Web进行访问(和运行),必须将其放在Web服务器能够访问的地方、 # 添加!#行并设置合适的文件权限。接下来依次介绍这三个步骤。 # 15.2.1 第一步:准备 Web 服务器 # 这里假设你能够访问Web服务器。换而言之,你能够将内容发布到Web。通常,要将内容发 # 布到Web,只需将网页、图像等放入特定的目录(在UNIX中通常为public_html)即可。如果你不 # 知道如何将内容发布到Web,请咨询Internet服务提供商(ISP)或系统管理员。 # 15.2.2 第二步:添加!#行 # 将脚本放到正确的位置(还可能给它指定特定的文件扩展名)后,必须在其开头添加一个!# # 行。第1章说过,通过添加!#行,无需显式地执行Python解释器就能执行脚本。通常,这只是提 # 供了便利,但对CGI脚本来说却至关重要,因为如果没有!#行,Web服务器将不知道如何执行脚 # 本。(Web服务器只知道脚本可能是使用Perl、Ruby等其他编程语言编写的。)一般而言,只需在 # 脚本开头添加如下行即可: # #!/usr/bin/env python # 请注意,它必须是第一行(之前没有空行)。如果这样做不管用,就得确定Python可执行文 # 件的准确位置,并在!#行中使用完整的目录,如下所示: # #!/usr/bin/python # 如果同时安装了Python 2和Python 3,可能需要将python替换为python3(前面的env解决方案 # 亦如此)。如果这样做也不管用,可能存在你看不到的错误,具体地说是!#行以\r\n而不是\n结 # 尾,把Web服务器搞糊涂了。请务必将脚本保存为UNIX风格的纯文本文件。 # 在Windows中,可使用Python可执行文件的完整路径,如下所示: # #!C:\Python36\python.exe # 15.2.3 第三步:设置文件权限 # 需要做的最后一件事情是设置合适的文件权限(至少当Web服务器运行在UNIX或Linux系统 # 中时如此)。必须确保谁都可以读取和执行你的脚本文件(否则Web服务器将无法运行它),同时 # 确保只有你才能写入(这样其他任何人都不能修改你的脚本)。 # 15.2.4 CGI 安全风险 # 使用CGI程序存在一些安全风险。如果你允许CGI脚本对服务器中的文件执行写入操作,那 # 么这可能被人利用来破坏数据——除非编写脚本时非常小心。同样,如果直接将用户提供的数据 # 作为Python代码(如使用exec或eval)或shell命令(如使用os.system或模块subprocess)执行, # 就可能执行恶意的命令,进而面临极大的风险。即便在SQL查询中使用用户提供的字符串也很危 # 险,除非你预先仔细审查这些字符串。SQL注入是一种常见的攻击系统的方式。 # 15.2.5 简单的 CGI 脚本 # 最简单的CGI脚本类似于代码清单15-4。 # 代码清单15-4 简单的CGI脚本 #!/usr/bin/env python print('Content-type: text/plain') print()# 打印一个空行,以结束首部 print('Hello, world!') # 15.2.6 使用 cgitb 进行调试 # 有时候,编程错误可能导致程序终止,并因未捕获的异常而显示栈跟踪。通过CGI运行程序 # 时,如果出现这种情况,可能导致Web服务器显示毫无帮助的错误消息甚至黑色网页。如果你能 # 够访问服务器日志(例如,如果你使用的是http.server),可能能够在这里找到蛛丝马迹。然而, # 为帮助调试CGI脚本,标准库提供了一个很有用的模块,名为cgitb(用于CGI栈跟踪)。通过导 # 入这个模块并调用其中的函数enable,可显示一个很有用的网页,其中包含有关什么地方出了问 # 题的信息。代码清单15-5演示了如何使用模块cgitb # 代码清单15-5 显示栈跟踪的CGI脚本(faulty.cgi) #!/usr/bin/env python import cgitb; cgitb.enable() print('Content-type: text/html\n') print(1/0) print('Hello, world!') # 15.2.7 使用模块 cgi # 到目前为止,所有CGI脚本都只生成输出,而没有使用任何形式的输入。输入是通过HTML # 表单(将在下一节介绍)以键值对(字段)的方式提供给CGI脚本的。在CGI脚本中,可使用模 # 块cgi中的FieldStorage类来获取这些字段。当你创建FieldStorage实例(应只创建一个)时,它 # 将从请求中取回输入变量(字段),并通过一个类似于字典的接口将它们提供给脚本。要访问 # FieldStorage中的值,可通过普通的键查找,但出于一些技术原因(与文件上传相关,这里不讨 # 论),FieldStorage的元素并不是你要的值。例如,即便你知道请求包含一个名为name的值,也不 # 能像下面这样做: # form = cgi.FieldStorage() # name = form['name'] # 而必须这样做: # form = cgi.FieldStorage() # name = form['name'].value # 15.2.8 简单的表单 # 有了处理用户请求的工具,该来创建用户可提交的表单了。这个表单可以是独立的页面,但 # 这里将它放在脚本中。 # 要深入地了解如何编写HTML表单(或HTML),可参考介绍HTML的优秀著作(当地书店可 # 能就有不少)。另外,在网上也能找到很多有关这个主题的信息。与往常一样,发现值得模仿的 # 优秀网页后,可在浏览器中查看其源代码,方法是从菜单中选择“查看源代码”之类的选项(具 # 体是哪个选项取决于你使用的浏览器)。 # 15.3 使用 Web 框架 # 对于重要的Web应用,大多数人都不会直接为其编写CGI脚本,而是选择使用Web框架,因 # 为它会替你完成很多繁重的工作。这样的框架有很多,后面将提及其中的几个,但现在要将注意 # 力放在既简单又有用的Flask(http://flask.pocoo.org)上。使用pip很容易安装这个框架。 # $ pip install flask # 假设你编写了一个计算幂的函数。 # def powers(n=10): # return ', '.join(str(2**i) for i in range(n)) # 而且想让每个人都能使用它!要使用Flask来实现这个目标,首先使用合适的名称实例化Flask # 类,并将这个函数的URL路径告诉它。 # from flask import Flask # app = Flask(__name__) # @app.route('/') # def powers(n=10): # return ', '.join(str(2**i) for i in range(n)) # 如果这个脚本名为powers.py,就可像下面这样让Flask运行它(这里假设是在UNIX风格的 # shell中): # $ export FLASK_APP=powers.py # $ flask run # * Serving Flask app "powers" # * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) # 最后两行是Flask的输出。如果你在浏览器中输入上面的URL,将看到函数powers返回的字符 # 串。你也可给这个函数指定更具体的路径。例如,如果使用route('/powers')而不是('/'),这个 # 函数将位于http://127.0.0.1:5000/powers。这样,你就可设置多个函数,每个函数的URL各不相同。 # 你甚至能向函数提供参数。要指定参数,可使用尖括号,例如'/powers/'。这样,斜杠 # 后面的内容将作为关键字参数n的值。但这样提供的是一个字符串,而这里需要的是一个整数。 # 为执行转换,可使用route('/powers/')。这样修改后,如果重新启动Flask,并访问URL # http://127.0.0.1:5000/powers/3,将得到输出1, 2, 4。 # Flask还有很多其他的功能,其文档也很容易理解。如果要尝试简单的服务器端Web应用开发, # 建议你看看这些文档。 # 其他 Web 应用框架 # 还有很多其他的Web框架,大小皆有。有的晦涩难懂,有些定期召开推广会议。表15-2列出 # 了几个流行的框架,更完整的清单请参阅Python网页(https://wiki.python.org/moin/WebFrameworks)。 # 表15-2 Python Web应用框架 # 名 称 网 站 # Django https://djangoproject.com # TurboGears http://turbogears.org # web2py http://web2py.com # Grok https://pypi.python.org/pypi/grok # Zope2 https://pypi.python.org/pypi/Zope2 # Pyramid https://trypyramid.com # 15.4 Web 服务:更高级的抓取 # Web服务有点像对计算机友好的网页。它们基于让程序能够通过网络交换信息的标准和协 # 议——通常其中一个程序请求信息或服务(客户端或服务请求者),而另一个程序提供信息或 # 服务(服务器或服务提供者)。确实,Web服务器很容易理解,而且看起来与前面讨论的网络编 # 程很像,不过也存在差别。 # Web服务通常运行在极高的抽象层级中,将HTTP(Web使用的协议)用作底层协议。在这个 # 协议上面,它们使用更为面向内容的协议(如XML格式)来对请求和响应进行编码。这意味着 # Web服务器可作为Web服务的平台。正如本节的标题指出的,它将Web抓取提高到另一个层级。 # 你可将Web服务看作为计算机客户(而不是人类)设计的动态网页。 # 有些Web服务标准非常复杂,但在不涉及任何复杂方面的情况下也能完成很多任务。本节将 # 简要地介绍这个主题,并提供在哪里能够找到所需工具和信息的指南。 # 15.5 小结 # 下面总结了本章介绍的主题。 #  屏幕抓取:指的是自动下载网页并从中提取信息。程序Tidy及其库版本是很有用的工具, # 可用来修复格式糟糕的HTML,然后使用HTTML解析器进行解析。另一种抓取方式是使 # 用Beautiful Soup,即便面对混乱的输入,它也可以处理。 #  CGI:通用网关接口是一种创建动态网页的方式,这是通过让Web服务器运行、与客户端 # 程序通信并显示结果而实现的。模块cgi和cgitb可用于编写CGI脚本。CGI脚本通常是在 # HTML表单中调用的。 #  Flask:一个简单的Web框架,让你能够将代码作为Web应用发布,同时不用过多操心Web # 部分。 #  Web应用框架:要使用Python开发复杂的大型Web应用,Web应用框架必不可少。对简单 # 的项目来说,Flask是不错的选择;但对于较大的项目,你可能应考虑使用Django或 # TurboGears。 #  Web服务:Web服务之于程序犹如网页之于用户。你可以认为,Web服务让你能够以更抽 # 象的方式进行网络编程。常用的Web服务标准包括RSS(以及与之类似的RDF和Atom)、 # XML-RPC和SOAP。

你可能感兴趣的:(python,前端,开发语言)