----用教授的方法学习。
目录
三个重要的主题:屏幕抓取、CGI和mod_python。
15.1 屏幕抓取
简单的屏幕抓取程序
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))
15.1.1 Tidy 和 XHTML 解析
1. Tidy是什么
Tidy是用于对格式不正确且不严谨的HTML进行修复的工具。
2. 获取Tidy
有多个用于Python的Tidy库包装器,至于哪个最新并非固定不变的。可像下面这样使用pip来找出可供使用的包装器:
$ pip search tidy |
一个不错的选择是PyTidyLib,可像下面这样安装它:
$ pip install pytidylib |
也可下载:https://download.csdn.net/download/weixin_38135241/89429925
https://download.csdn.net/download/weixin_38135241/89429925
https://download.csdn.net/download/weixin_38135241/89429930
3. 为何使用XHTML
XHTML和旧式HTML的主要区别在于,XHTML非常严格,要求显式地结束所有的元素(至少就我们当前的目标而言如此)。
4. 使用HTMLParser
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) | 遇到未知声明时调用 |
使用模块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):
if self.in_link:
self.chunks.append(data)
def handle_endtag(self, tag):
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()
15.1.2 Beautiful Soup
Beautiful Soup是一个小巧而出色的模块,用于解析你在Web上可能遇到的不严谨且格式糟糕的HTML。
下载:https://download.csdn.net/download/weixin_38135241/89429954
https://download.csdn.net/download/weixin_38135241/89429955
https://download.csdn.net/download/weixin_38135241/89429956
下载并安装Beautiful Soup易如反掌。与大多数包一样,你可使用pip来完成这种任务。
$ 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.section('h2'):
jobs.add('{} ({})'.format(job.a.string, job.a['href']))
print('\n'.join(sorted(jobs, key=str.lower)))
15.2 使用 CGI 创建动态网页
CGI是一种标准机制,Web服务器可通过它将(通常是通过Web表达提供的)查询交给专用程序(如你编写的Python程序),并以网页的方式显示查询结果。这是一种创建Web应用的简单方式,让你无需编写专用的应用程序服务器。
15.2.1 第一步:准备 Web 服务器
$ python -m http.server --cgi Serving HTTP on 0.0.0.0 port 8000 ... |
15.2.2 第二步:添加#!行
一般而言,只需在脚本开头添加如下行即可:
#!/usr/bin/env python |
请注意,它必须是第一行(之前没有空行)。如果这样做不管用,就得确定Python可执行文件的准确位置,并在!#行中使用完整的目录,如下所示:
#!/usr/bin/python |
在Windows中,可使用Python可执行文件的完整路径,如下所示:
#!C:\Python36\python.exe |
15.2.3 第三步:设置文件权限
必须确保谁都可以读取和执行你的脚本文件(否则Web服务器将无法运行它),同时确保只有你才能写入(这样其他任何人都不能修改你的脚本)。
在UNIX中,修改文件权限(或文件模式)的命令为chmod。要修改文件权限,只需通过普通用户账户或专为完成Web任务而建立的账户执行下面的命令。
chmod 755 somescript.cgi |
要让它能够修改文件,必须显式地赋予它权限。要设置这样的文件权限,可使用如下命令:
chmod 666 editable_file.txt |
15.2.4 简单的 CGI 脚本
简单的CGI脚本
#!/usr/bin/env python
print('Content-type: text/plain')
print()# 打印一个空行,以结束首部
print('Hello, world!')
15.2.5 使用 cgitb 进行调试
显示栈跟踪的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.6 使用模块 cgi
从FieldStorage中获取单个值的CGI脚本(simple2.cgi)
#!/usr/bin/env python
import cgi
form = cgi.FieldStorage()
name = form.getvalue('name', 'world')
print('Content-type: text/plain\n')
print('Hello, {}!'.format(name))
15.3 使用 Web 框架
下载:
使用pip很容易安装这个框架
$ pip install flask |
你编写了一个计算幂的函数。而且想让每个人都能使用它!要使用Flask来实现这个目标,首先使用合适的名称实例化Flask类,并将这个函数的URL路径告诉它。
powers.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def powers(n=10):
return ', '.join(str(2**i) for i in range(n))
----end