文章大纲
WEB 是 Python 中的一大方向,涉及的内容很广,这里只尝试三个主题:屏幕抓取、CGI和 WEB 框架。
屏幕抓取
屏幕抓取是通过程序下载网页并从中提取信息的过程。
整个流程可以归纳为下载数据并对其进行分析,可以使用 urllib
来获取网页的 HTML 代码,然后使用正则表达式来匹配所需信息。
urllib
与 re
获取网页数据的示例:
from urllib.request import urlopen
import re
p = re.compile('<a href="(/jobs/\\d+)/">(.*?)</a>')
text = urlopen('http://python.org/jobs').read().decode()
for url, name in p.findall(text):
print('{} ({})'.format(name, url))
使用此类方式抓取屏幕有以下缺点:
- 正则表达式不容易理解
- 无法处理独特的 HTML 内容,如 HTML 字符实体
Tidy 和 XHTML 解析
如果每个网页包含的 XHTML 都正确有效,解析工作将变得简单,如果存在标签缺失的情况下就不好处理了。
Tidy
Tidy 用于对格式不正确且不严谨的 HTML 进行修复的工具。
获取 Tidy
获取 Tidy 的方式有多种,如果使用 UNIX 系统,可以通过软件包管理器安装打包好的软件,如,在 Fedora 中可以通过 dnf install -y tidy.x86_64
进行安装,也可以通过 pip
进行安装,如 pip install pytidylib
。
实现 tidy
的 Python 包有很多,也可以选择安全其它包。
为何使用 XHTML
XHTML 相对于 HTML 的主要区别在于 XHTML 非常严格,要求显示的结束所有的元素.
使用 HTMLParser
使用 HTMLParser
意味着继承它,并重写各种事件处理方法。
下面列出了相关的方法以及解析器在什么时候自动调用他们。
回调方法 | 何时被调用 |
---|---|
handle_starttag(tag, attrs) | 遇到开始标签时调用 |
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) | 遇到未知声明时调用 |
使用模块 HTMLParser
的屏幕抓取示例:
from urllib.request import urlopen
from html.parser import HTMLParser
def isjob(url):
try:
a, b, c, d = url.split('/')
except ValueError:
return False
return a == d == '' and b == 'jobs' and c.isdigit()
class Scraper(HTMLParser):
in_link = False
def handle_starttag(self, tag, attrs):
attrs = dict(attrs)
url = attrs.get('href', '')
if tag == 'a' and isjob(url):
self.url = url
self.in_link = True
self.chunks = []
def handle_data(self, data: str):
if self.in_link:
self.chunks.append(data)
def handle_endtag(self, tag: str):
if tag == 'a' and self.in_link:
print('{} ({})'.format(''.join(self.chunks), self.url))
self.in_link = False
text = urlopen('http://python.org/jobs').read().decode()
parser = Scraper()
parser.feed(text)
parser.close()
Beautiful Soup
Beautiful Soup 是一个小巧出色的模块,用于解析在 Web 上可能遇到的不严谨且格式糟糕的 HTML。
通过 pip install beautifulsoup4
进行安装。
使用 Beautiful Soup 的屏幕抓取示例:
from urllib.request import urlopen
from bs4 import BeautifulSoup
text = urlopen('http://python.org/jobs').read()
soup = BeautifulSoup(text, 'html.parser')
jobs = set()
for job in soup.body.select('h2'):
try:
jobs.add('{} ({})'.format(job.a.string, job.a['href']))
except AttributeError:
pass
print('\n'.join(sorted(jobs, key=str.lower)))
使用 CGI 创建动态网页
通用网关接口,是一种标准机制,Web 服务器可通过它将查询交给专用程序,并以网页的方式显示查询结果。
第一步:准备 Web 服务器
可通过 Python 中的 http.server
模块,直接运行一个临时的 Web 服务器。如果指定了 --cgi
选项,启动的服务器将支持 CGI 。
(venv) [hcai@P1-Gen4 Chapter_15]$ python -m http.server --cgi
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
CGI 程序必须放置在可通过 Web 访问的目录中,常见的方式:
- 将脚本放在子目录
cgi-bin
中 - 将脚本文件的后缀名指定为
.cgi
第二步:添加 !# 行
将脚本放置到正确位置后,必须在开头添加一个 !#
的行,没有的话,Web 服务器将不知道如何执行脚本。
通常只需在脚本开头添加以下行即可:!#/usr/bin/env python
第三步:设置文件权限
必须确保脚本能够被读取和执行的权限,可以设置为 755
。
简单的 CGI 脚本示例:
#!/home/hcai/pythonProject/Chapter_15/venv/bin/python
print('Context-type: text/html')
print()
print('<h1>Hello World!</h1>')
使用 cgitb 进行调试
如果 CGI 脚本出现错误,Web 页面没有任何提示,为了能方便捕获异常显示堆栈信息,可以启动 cgitb
模块。
显示栈跟踪的 CGI 脚本:
#!/home/hcai/pythonProject/Chapter_15/venv/bin/python
import cgitb; cgitb.enable()
print('Content-type: text/html\n')
print(1/0)
print('<h1>Hello World!</h1>')
浏览器访问后显示的栈信息:
使用模块 cgi
在 CGI 脚本中,可以通过 cgi
模块中的 FieldStorage
类来获取输入的字段。
示例一:
#!/home/hcai/pythonProject/Chapter_15/venv/bin/python
import cgi
form = cgi.FieldStorage()
name = form.getvalue('name', 'World')
print('Content-type: text/plain\n')
print('Hello, {}!'.format(name))
示例二:
#!/home/hcai/pythonProject/Chapter_15/venv/bin/python
import cgi
form = cgi.FieldStorage()
name = form.getvalue('name', 'world')
print("""Content-type: text/html
<html>
<head>
<title>Greeting Page</title>
</head>
<body>
<h1>Hello, {}!</h1>
<form action='simple4.cgi'>
Change name <input type='text' name='name' />
<input type='submit' />
</form>
</body>
</html>
""".format(name))
使用 Web 框架
Web 框架可以帮助完成繁琐的工作,常用的 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 |
Flask 框架使用的简单示例:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def powers(n=10):
return ', '.join(str(2**i) for i in range(n))