您的位置:首页 > 编程语言 > Python开发

Python Web概述

2017-07-24 16:48 239 查看
三个概念:

HTTP (超文本传输传输协议)

规定了网络客户端和服务器之间如何交换请求和响应

HTML(超文本标记语言)

结果的展示格式

URL(统一资源定位符)

唯一表示服务器和服务器上资源的方法

一个最简单的场景:

一个Web客户端通过HTTP连接到一个Web服务器,请求一个URL,收到HTML。

Web客户端

互联网最底层的网络传输使用的是传输控制协议/因特网协议,更常用的叫法是TCP/IP。这些协议会在计算机之间传输字节,但是并不关心这些字节的含义,后者由更高层的协议——用于特定目的的语法定义——来处理。HTTP是Web数据交换的标准协议。

Web是一个客户端——服务器系统。客户端向服务器发起请求:它会创建一个TCP/IP连接,通过HTTP发送URL和其他信息并接收一个响应。

响应的格式也由HTTP定义。其中包括请求的状态以及(如果请求成功)响应的数据和格式。

Python的标准Web库

在Python2中,Web客户端和服务器模块结构都比较散乱。Python3的目标之一就是把这些模块打包成两个包

http会处理所有客户端-服务器HTTP请求的具体细节:

client会处理处理客户端的部分

server会协助你编写Python Web服务器程序

cookies和cookiejar会处理cookie,cookie可以在请求中存储数据

urllib是基于http的高层库:

request处理客户端请求

response处理服务器端的响应

parse会解析URL

例子



HTTP状态码:

1xx(信息)

服务器收到了请求,但是需要客户端发送一些额外的信息。

2xx(成功)

请求成功。除了200以外,其他的状态码还会包含一些特殊含义。

3xx(重定向)

资源位置发生改变,所以响应会返回一个新的URL给客户端。

4xx(客户端错误)

客户端发送错误,比如最出名的404(页面不存在)。

5xx(服务端错误)

500是最常见的错误。你可能也见到过502(网关错误),这表示Web服务器程序和后端的应用服务器之间无法连接。

响应的HTTP头:

Content-Type (MIME类型)

Set-Cookie(用来在多次访问之间追踪你的活动)

下面代码可以得到最终返回的数据是什么(不是HTTP首部的部分)

data = conn.read()
print(data)


抛开标准库:requests

pip install requests


在大多数情况下,使用requests可以让Web客户端开发变得更加简单。

例子

import requests
url = 'http://www.baidu.com'
resp = requests.get(url)
print(resp.text)


Web服务端

最简单的Python Web服务器

可以用一行Python代码启动一个简单的Web服务器



现在你可以通过相对路径来请求文件,它们会被Web服务器返回。如果你在Web浏览器中输入http://localhost:8000,会看到一个目录列表:



Web服务器会打印出下面这样的访问日志:



- 127.0.0.1<=>localhost是客户端的IP地址

- 第一个”-“是远程用户名,本例为空

- 第二个”-“是登陆用户名,本例中是可选的,为空

- [29/Jul/2017 16:30:26]是访问日期和时间

- “GET / HTTP/1.1”是指Web服务器收到的指令

- 最后的200表示Web服务器返回的HTTP状态码

默认的端口数是8000,你也可以指定其他的数字:

python -m http.server 9999


这个Python特有的Web服务器很适合用作快速测试。一定不要把这个简单的Web服务器用在真正的产品级网站中。Nginx和Apache等传统Web服务器可以更快地处理静态文件。此外,这个简单的Web服务器不能处理动态内容,其它更高端的Web服务器可以接收参数并返回动态内容。

关于0.0.0.0这个ip地址的含义

0.0.0.0 is not the URL you should be visiting. When a Python says it is serving on 0.0.0.0 it means it is listening for all TCP traffic that ends up at that machine no matter the hostname or IP that was requested.

But, if you change it such that the socket listens on 127.0.0.1 or ‘localhost’, then unless the request was specifically to that IP/hostname, it won’t respond to the request.

例子

我们在java编程中使用ServerSocket做网络侦听,通常只需要如下代码:

ServerSocket serverSock=new ServerSocket(8888);
serverSock.accept();


假如我的主机ip为:10.10.152.8

用以上代码做侦听,127.0.0.1:8888或者10.10.152.8:8888都可以连上

但大家有没有想过过,这个ServerSocket到底使用哪个IP在做侦听?(是10.10.152.8?),因此做以下的实验:

如果我们将以上代码改成显式绑定:

ServerSocket ss=new ServerSocket();
String ip=“10.10.152.8″;
int port=8888;
InetSocketAddress addr=new InetSocketAddress(ip,port);
ss.bind(addr);
ss.accept();


你会发现,127.0.0.1:8888是无法访问的!

同理,如果将ip改成127.0.0.1,那么10.10.152.8:8888是无法访问的。

实际上,背后的秘密就在与0.0.0.0这个IP,他可以代表本机的所有IP地址,但这个IP并不是真是存在的,我们ping不通它,如果将ip改成0.0.0.0:

ServerSocket ss=new ServerSocket();
String ip=“0.0.0.0″;
int port=888
4000
8;
InetSocketAddress addr=new InetSocketAddress(ip,port);
ss.bind(addr);
ss.accept();


我们会发现,这和默认行为是一样的,127.0.0.1:8888或者10.10.152.8:8888都可以连上

Web服务器网关接口

现在只提供简单的文件服务已经不能满足我们了,我们要能够动态运行程序的Web服务器

在Web发展的早期,出现了通用网关接口(CGI),客户端可以通过它来让Web服务器运行外部程序并返回结果。CGI也会从Web服务器获取用户输入的参数并传给外部程序。然而,对于每个用户请求都需要运行一次程序,这样很难扩大用户规模,因为即使程序很小,启动时还是会有明显的等待时间更多关于CGI&更多关于fork and Exec

为了避免启动延迟,人们开始把语言解释器合并到Web服务器中。Apache可以通过mod_php模块来运行PHP,通过mod_perl模块来运行Perl,通过mod_python来运行Python。这样,动态语言的代码就可以直接在持续运行的Apache进程中执行(同一个进程),不用再调用外部程序

另一种方式是在一个独立的持续运行的程序中运行动态语言,并让它和Web服务器进行通信,例如FastCGI和SCGI。

Web服务器网关接口(WSGI)是一个通用的API,连接Python Web应用和Web服务器。本章接下来介绍的所有Python Web框架和Web服务器都是用了WSGI。

注意:

Web应用和Web服务器是两种很不相同的东西,逻辑上是分开的东西。我们常用的框架(如Bottle、Flask等)指的都是Web应用,通过接口与Web服务器交互(如满足WSGI规范的接口)。而常用的Web服务器有apache、nginx等。

框架

Web服务器会处理HTTP和WSGI的具体细节,但真正的网站是你使用框架写出的PYthon代码。

框架可能会具备的特性:

处理客户单请求和服务器相应

路由 | 解析URL并找到对应的服务器文件或者Python服务器代码

模板 | 把服务端数据合并成HTML页面

认证和授权 | 处理用户名、密码和权限

Session | 处理用户在多次请求之间需要存储的数据

Bottle

Bottle(瓶子)只包含一个简单的Python文件,所以非常易于使用并且易于部署。

pip install bottle




Bottle使用route装饰器来关联URL和函数。在本例中,/(首页)会被home()函数处理。

run()函数会执行bottle内置的Python测试用的Web服务器。你也可以使用其他Web服务器,但是在开发和测试时它非常有用。

把HTML硬编码到代码中是很不合适的,我们创建一个单独的HTML文件index.html并写入下面的内容:

My <b>new</b> and <i>improved</i> home page!!!


from bottle import route, run, static_file

@route('/')
def main():
# 调用static_file()时,我们指定的是root目录(在本例中是'.',也就是当前目录)下的index.html文件
return static_file('index.html', root='.')

run(host='localhost'. port=9999)


可以指定URL中的参数并使用它:

from bottle import route, run, static_file

@route('/')
def home():
return static_file('index.html', 'root='.')

# 访问http://localhost:9999/echo/<thing>
@route('/echo/<thing>')
def echo(thing):
return 'Say hello to my little friend: %s!" % thing

run(host='localhost', port=9999)


我们定义了一个新函数echo(thing)(函数可以命名为其他的名字如next(thing)),并且在URL中指定了一个字符串参数。路由中的thing表示URL中/echo/之后的内容都会被复制给字符串参数thing,然后传入echo函数。

bottle还有许多其他的特性,例如你可以试着在调用run()时加上这些参数:

debug=True,如果出现HTTP错误,就会创建一个调试页面

reloader=True,如果你修改了任何Python代码,浏览器中的页面会重新载入

Flask

Bottle是一个非常优秀的入门框架。但如果你需要更多的功能,那就试试Flask吧。Flask和Bottle一样易用,同时还支持很多专业Web开发需要的扩展功能,如Facebook认证和数据库集成。Flask包中自带了werkzeug WSGIjinja2模板库

pip install flask


我们用flask来重写一下最后那个bottle例子。首先需要进行一些修改。

Flask默认的静态文件目录是static,默认的静态文件URL由/static开始。我们把文件夹改成’.’(当前目录),把URL前缀改成”(空),这样URL/可以被映射到文件index.html。



在run()函数中,设置debug=True可以启动代码自动重载;bottle把这个参数拆成两个,debug和reload。当debug=Ture,在调用run时,如果代码中出现异常,Flask会返回一个特殊的网页,其中会包含一些有用的信息,比如错误类型和错误位置。此外,你还可以使用一些命令来查看服务器程序中变量的值。在生产环境中不要把debug设置为True,否则可能会暴露出太多信息,有安全隐患

from flask import Flask
app = Flask(__name__, static_folder='.', static_url_path='')

@app.route('/')
def home():
return app.send_static_file('index.html')
@app.route('/echo/<thing>')
def echo(thing):
return 'Say hello to my little friend: %s' % thing

app.run(port=9999, debug=True)


Flask能做什么bottle做不了的事情呢?

Flask内置了jinja2,一个极具扩展性的模板系统。

例子

1.

创建文件目录



2.1

Python代码

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/echo/<thing>/<place>')
def echo(thing, place):
return render_template('flask.html', thing=thing, place=place)

@app.route('/')
def home():
return app.send_static_file('index.html')

app.run(port=9999, debug=True)


3.1

利用浏览器访问



2.2

from flask import Flask, render_template, request

app = Flask(__name__)

# 还可以用GET参数来传递参数
@app.route('/echo/')
def echo():
thing = request.args.get('thing')
place = request.args.get('place')
return render_template('flask.html', thing=thing, place=place)

app.run(port=9999, debug=True)


from flask import Flask, render_template, request

app = Flask(__name__)

# 还可以用GET参数来传递参数
@app.route('/echo/')
def echo():
kwargs = {}
kwargs['thing'] = request.args.get('thing')
kwargs['place'] = request.args.get('place')
return render_template('flask.html', **kwargs)

app.run(port=9999, debug=True)


3.2

利用浏览器访问



其他框架

小型框架,比如bottle和flask,不能直接支持数据库,尽管有一些插件可以实现。

如果你需要开发基于数据库的网站并且数据库的结构不会经常发生变化,那最好试试大型的Python Web框架。现在主流的框架有以下这些:

django

django是最流行的,尤其是大型网站很喜欢用它。它有ORM功能,可以在网页中自动应用典型的CRUD功能。你也可以不用django自带的ORM,可以选择SQLAlchemy或者直接使用SQL查询语句。

web2py

和django功能类似,只是风格不同。

pyramid

诞生于最早的pylons项目,和django很像。

turbogears

这个框架支持ORM、多种数据库以及多种模板语言。

wheezy.web

这个是一个比较新的框架,专为性能而生。在最近的测试中,它比其他框架都快

这个在线表格列举对比了上述的这些框架

如果你的网站使用的关系数据库,就可以不使用大型框架,直接用bottle、flask这类框架结合关系数据库模块即可。也可以使用SQLAlchemy来屏蔽数据库的差异,直接写通用SQL代码就行。相比特定的ORM语法,大多数程序员更熟悉SQL。

当然,你完全可以不使用关系型数据库,如果你的数据结构差异很大——不同行的同一列差别很大——那你或许应该试试无模式数据库,比如NoSQL数据库

Web服务器

到目前为止,我们使用的Web服务器都很简单:不是标准库的http.server就是Bottle和Flask自带的调试用服务器。在生产环境中,你需要用更快的Web服务器来运行Python。

下面是常用的选择:

apache加上mod_wsgi模块

nginx加上uWSGI应用服务器

apache可能是最流行的,nginx更稳定并且占用内存更少。

Apache

Apache Web服务器中最好用的WSGI模块是mod_wsgi。这个模块可以在Apache进程中运行Python代码,也可以在Apache进程中运行Python代码,也可以在独立进程中运行Python代码并和Apache进行通信

例子(Apache + mod_wsgi + bottle)

1.嵌入模式(WSGIScriptAlias)

在嵌入模式中运行了mod_wsgi,在这个模式下它是apache的一部分(在同一进程内)。

2.守护模式(WSGIDaemonProcess)

在守护模式中运行mode_wsgi,在这个模式下会产生一个或多个独立于apache的进程。

更多

Nginx Web服务器

Nginx Web服务器没有内嵌的Python模块。它通过一个独立的WSGI服务器(如uWSGI)来和Python程序通信。把它们结合在一起可以实现高性能
1091e
并且可配置的Python Web开发平台


如何结合Flask、nginx和uWSGI

其它

下面是一些类似apache和nginx的基于Python的WSGI服务器,使用多进程和/或线程来处理并发请求:

uwsgi

cherrypy

pylons

下面是一些基于事件的服务器,只使用单线程但不会阻塞:

tornado

gevent

gunicorn

Web服务和自动化

传统的Web客户端和服务器应用会生成并使用HTML页面。然而,Web逐渐演变出了许多非HTML的数据传输格式

webbrowser模块

标准库webbrowser可以控制你的浏览器。

import webbrowser
url = 'http://www.python.org/'
# 在浏览器中打开url
webbrowser.open(url)
# 在浏览器新窗口中打开url
webbrowser.open_new_tab(url)


Web API和表述性状态传递

通常来说,数据只存在于网页内。如果你想获取数据,需要在Web浏览器中访问网页并阅读数据。如果网站作者在你最后一次访问之后做了什么改动,数据的位置和格式就可能发生变化

除了发布网页,你可以通过应用编程接口(API)来提供数据。客户端通过URL来范文你的服务并从响应中获取状态和数据。数据并不是HTML网页,而是更容易被程序处理的格式,比如JSON和XML

表述性状态传递(REST)就是一个Web接口,即定义一组可以访问Web服务的URL。

RESTful服务会用特定的方式来使用HTTP动词:

HEAD(获取资源的信息,但不包括数据)

GET(GET会从服务器取回资源的数据)

POST(更新服务器的数据。通常它会被用在HTML的表单和Web API中)

PUT(创建一个新资源)

DELETE(删除一些东西)

JSON

JSON非常适用在Web客户端和服务器的数据交换中。它在基于Web的API中非常流行,比如OpenStack。

更多

抓取数据

Scrapy

Scrapy是一个框架,并不是类似BeautifulSoup的模块。它会做更多事,不过也更难设置。

pip install scrapy


文档

在线教程

用BeautifulSoup来抓取HTML

如果你已经拿到一个网站的HTML数据并且想从中提取数据,BeautifulSoup是一个不错的选择

解析HTML比想象中要难得多,因为互联网上的HTML在技术角度通常是不合法的:没有闭合的标签、不正确的嵌套以及其他复杂的东西。如果你自己尝试过用正则表达式来解析HTML,你一定遇到过这些麻烦事。

pip install beautifulsoup4


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: