Python 基础学习17:Web

WEB 是 Python 中的一大方向,涉及的内容很广,这里只尝试三个主题:屏幕抓取、CGI和 WEB 框架。

屏幕抓取

屏幕抓取是通过程序下载网页并从中提取信息的过程。
整个流程可以归纳为下载数据并对其进行分析,可以使用 urllib 来获取网页的 HTML 代码,然后使用正则表达式来匹配所需信息。

urllibre 获取网页数据的示例:

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 框架有:

名称网站
Djangohttps://djangoproject.com
TurboGearshttp://turbogears.org
web2pyhttp://web2py.com
Grokhttps://pypi.python.org/pypi/grok
Zope2https://pypi.python.org/pypi/Zope2
Pyramidhttps://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))

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

滚动至顶部