Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a2d6a2f

Browse files
committed
sync to 502
1 parent eb2feb5 commit a2d6a2f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+33645
-12269
lines changed

‎314.md‎

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
>"Pay attention to what you hear; the measure you give will be the measure you get, and still more will be given you. For to those who have, more will be given; and from those who have nothing, even what they have will be taken away."(MARK 4:24-25)
2+
3+
#模板转义
4+
5+
列位看官曾记否?在[《玩转字符串(1)》](https://github.com/qiwsir/ITArticles/blob/master/BasicPython/107.md)中,有专门讲到了有关"转义"问题,就是在python的字符串中,有的符号要想表达其本意,需要在前面加上`\`符号,例如单引号,如果要在字符串中表现它,必须写成`\'单引号里面\'`样式,才能实现一对单引号以及里面的内容,否则,它就表示字符串了。
6+
7+
在HTML代码中,也有类似的问题,比如`>`等,就是代码的一部分,如果直接写,就不会显示在网页里,要向显示,同样需要转义。另外,如果在网页中有表单,总会有别有用心的人向表单中写点包含`>`等字符的东西,目的就是要攻击你的网站,为了防治邪恶之辈,也需要将用户输入的字符进行转义,转化为字符实体,让它不具有HTML代码的含义。
8+
9+
>转义字符串(Escape Sequence)也称字符实体(Character Entity)。在HTML中,定义转义字符串的原因有两个:第一个原因是像"<"和">"这类符号已经用来表示HTML标签,因此就不能直接当作文本中的符号来使用。为了在HTML文档中使用这些符号,就需要定义它的转义字符串。当解释程序遇到这类字符串时就把它解释为真实的字符。在输入转义字符串时,要严格遵守字母大小写的规则。第二个原因是,有些字符在ASCII字符集中没有定义,因此需要使用转义字符串来表示。
10+
11+
##模板自动转义
12+
13+
Tornado 2 开始的模板具有自动转义的功能,这让开发者省却了不少事情。看一个例子。就利用上一讲中建立的开发框架。要在首页模板中增加一个表单提交功能。
14+
15+
修改template/index.html文件,内容如下:
16+
17+
<DOCTYPE html>
18+
<html>
19+
<head>
20+
<title>Loop in template</title>
21+
<link rel="stylesheet" type="text/css" href="{{ static_url('css/style.css')}}">
22+
</head>
23+
<body>
24+
<h1>aaaAAA</h1>
25+
<p>There is a list, it is <b>{{info}}</b></p>
26+
<p>I will print the elements of this list in order.</p>
27+
{% for element in info %}
28+
<p>{{element}}</p>
29+
{% end %}
30+
<br>
31+
{% for index,element in enumerate(info) %}
32+
<p>info[{{index}}] is {{element}}
33+
{% if element == "python" %}
34+
<p> <b>I love this language--{{element}}</b></p>
35+
{% end %}
36+
{% end %}
37+
38+
{% if "qiwsir@gmail.com" in info %}
39+
<p><b>A Ha, this the python lesson of LaoQi, It is good! His email is {{info[2]}}</b></p>
40+
{% end %}
41+
<h2>Next, I set "python-tornado"(a string) to a variable(var)</h2>
42+
{% set var="python-tornado" %}
43+
<p>Would you like {{var}}?</p>
44+
<!--增加表单-->
45+
<form method="post" action="/option">
46+
<p>WebSite:<input id="website" name="website" type="text"></p>
47+
<p><input type="submit" value="ok,submit"></p>
48+
</form>
49+
</body>
50+
</html>
51+
52+
在增加的表单中,要将内容以`post`方法提交到`"/option"`,所以,要在url.py中设置路径,并且要建立相应的类。
53+
54+
然后就在handler目录中建立一个新的文件,命名为optform.py,其内容就是一个类,用来接收index.html中`post`过来的表单内容。
55+
56+
#!/usr/bin/env python
57+
#coding:utf-8
58+
59+
import tornado.web
60+
61+
import sys
62+
reload(sys)
63+
sys.setdefaultencoding('utf-8')
64+
65+
class OptionForm(tornado.web.RequestHandler):
66+
def post(self):
67+
website = self.get_argument("website") #接收名称为'website'的表单内容
68+
self.render("info.html",web=website)
69+
70+
为了达到接收表单post到上述类中内容的目的,还需要对url.py进行如下改写:
71+
72+
#!/usr/bin/env python
73+
#coding:utf-8
74+
75+
import sys
76+
reload(sys)
77+
sys.setdefaultencoding('utf-8')
78+
79+
from handler.index import IndexHandler
80+
from handler.optform import OptionForm
81+
url=[
82+
(r'/', IndexHandler),
83+
(r'/option', OptionForm),
84+
85+
]
86+
87+
看官还要注意,我在新建立的optform.py中,当接收到来自表单内容之后,就用另外一个模板`info.html`显示所接收到的内容。这个文件放在template目录中,代码是:
88+
89+
<DOCTYPE html>
90+
<html>
91+
<head>
92+
<title>Loop in template</title>
93+
<link rel="stylesheet" type="text/css" href="{{ static_url('css/style.css')}}">
94+
</head>
95+
<body>
96+
<h1>My Website is:</h1>
97+
<p>{{web}}</p>
98+
</body>
99+
</html>
100+
101+
这样我们就完成表单内容的提交和显示过程。
102+
103+
从上面的流程中,看官是否体验到这个框架的优势了?不用重复敲代码,只需要在框架内的不同地方增加内容,即可完成网站。
104+
105+
演示运行效果:
106+
107+
我在表单中输入了`<script>alert('bad script')</script>`,这是多么阴险毒辣呀。
108+
109+
![](https://raw.githubusercontent.com/qiwsir/ITArticles/master/Pictures/31401.png)
110+
111+
然而我们的tornado是不惧怕这种攻击的,因为它的模板自动转义了。当点击按钮提交内容的时候,就将那些阴险的符号实体化,成为转义之后的符号了。于是就这样了:
112+
113+
![](https://raw.githubusercontent.com/qiwsir/ITArticles/master/Pictures/31402.png)
114+
115+
输入什么,就显示什么,不会因为输入的内容含有阴险毒辣的符号而网站无法正常工作。这就是转义的功劳。
116+
117+
##不转义的办法
118+
119+
在tornado中,模板实现了自动转义,省却了开发者很多事,但是,事情往往没有十全十美的,这里省事了,一定要在别的地方费事。例如在上面那个info.html文件中,我打算在里面加入我的电子信箱,但是要像下面代码这样,设置一个变量,主要是为了以后修改方便和在其它地方也可以随意使用。
120+
121+
<DOCTYPE html>
122+
<html>
123+
...(省略)
124+
<body>
125+
<h1>My Website is:</h1>
126+
<p>{{web}}</p>
127+
{% set email="<a href='mailto:qiwsir@gmail.com'>Connect to me</a>"%}
128+
<p>{{email}}</p>
129+
</body>
130+
</html>
131+
132+
本来希望在页面中出现的是`Connect to me`,点击它之后,就直接连接到发送电子邮件。结果,由于转义,出现的是下面的显示结果:
133+
134+
![](https://raw.githubusercontent.com/qiwsir/ITArticles/master/Pictures/31403.png)
135+
136+
实现电子邮件超链接未遂。
137+
138+
这时候,就需要不让模板转义。tornado提供的方法是:
139+
140+
- 在Application函数实例化的时候,设置参数:autoescape=None。这种方法不推荐适应,因为这样就让全站模板都不转意了,看官愿意尝试,不妨进行修改试一试,我这里就不展示了。
141+
- 在每个页面中设置{% autoescape None %},表示这个页面不转义。也不推荐。理由,自己琢磨。
142+
- 以上都不推荐,我推荐的是:{% raw email %},想让哪里不转义,就在那里用这种方式,比如要在email超级链接那里不转移,就写成这样好了。于是修改上面的代码,看结果为:
143+
144+
![](https://raw.githubusercontent.com/qiwsir/ITArticles/master/Pictures/31404.png)
145+
146+
如此,实现了不转义。
147+
148+
以上都实现了模板的转义和不转义。
149+
150+
##url转义
151+
152+
本来模板转义和不转义问题已经交代清楚了。怎奈上周六一个朋友问了一个问题,那个问题涉及到url转义问题,于是在这里再补上一段,专门谈谈url转义的问题。
153+
154+
有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用它们的编码了。编码的格式为:%加字符的ASCII码,即一个百分号%,后面跟对应字符的ASCII(16进制)码值。例如 空格的编码值是"%20"。
155+
156+
在python中,如果用utf-8写了一段地址,如何转义成url能够接收的字符呢?
157+
158+
在python中有一个urllib模块:
159+
160+
>>> import urllib
161+
162+
>>> #假设下面的url,是utf-8编码
163+
>>> url_mail='http://www.itdiffer.com/email?=qiwsir@gmail.com'
164+
165+
>>> #转义为url能够接受的
166+
>>> urllib.quote(url_mail)
167+
'http%3A//www.itdiffer.com/email%3F%3Dqiwsir%40gmail.com'
168+
169+
反过来,一个url也能转移为utf-8编码格式,请用urllib.unquote()
170+
171+
下面抄录帮助文档中的内容,供用到的朋友参考:
172+
173+
quote(s, safe='/')
174+
quote('abc def') -> 'abc%20def'
175+
176+
Each part of a URL, e.g. the path info, the query, etc., has a
177+
different set of reserved characters that must be quoted.
178+
179+
RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists
180+
the following reserved characters.
181+
182+
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
183+
"$" | ","
184+
185+
Each of these characters is reserved in some component of a URL,
186+
but not necessarily in all of them.
187+
188+
By default, the quote function is intended for quoting the path
189+
section of a URL. Thus, it will not encode '/'. This character
190+
is reserved, but in typical usage the quote function is being
191+
called on a path where the existing slash characters are used as
192+
reserved characters.
193+
194+
unquote(s)
195+
unquote('abc%20def') -> 'abc def'.
196+
197+
quote_plus(s, safe='')
198+
Quote the query fragment of a URL; replacing ' ' with '+'
199+
200+
unquote_plus(s)
201+
unquote('%7e/abc+def') -> '~/abc def'
202+
203+
转义是网站开发中要特别注意的地方,不小心或者忘记了,就会纠结。
204+

‎401.md‎

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#requests库
2+
3+
**作者:1world0x00**(说明:在入选本教程的时候,我进行了适当从新编辑)
4+
5+
requests是一个用于在程序中进行http协议下的get和post请求的库。
6+
7+
##安装
8+
9+
easy_install requests
10+
11+
或者用
12+
13+
pip install requests
14+
15+
安装好之后,在交互模式下运行:
16+
17+
>>> import requests
18+
>>> dir(requests)
19+
['ConnectionError', 'HTTPError', 'NullHandler', 'PreparedRequest', 'Request', 'RequestException', 'Response', 'Session', 'Timeout', 'TooManyRedirects', 'URLRequired', '__author__', '__build__', '__builtins__', '__copyright__', '__doc__', '__file__', '__license__', '__name__', '__package__', '__path__', '__title__', '__version__', 'adapters', 'api', 'auth', 'certs', 'codes', 'compat', 'cookies', 'delete', 'exceptions', 'get', 'head', 'hooks', 'logging', 'models', 'options', 'packages', 'patch', 'post', 'put', 'request', 'session', 'sessions', 'status_codes', 'structures', 'utils']
20+
21+
从上面的列表中可以看出,在http中常用到的get,cookies,post等都赫然在目。
22+
23+
#get请求
24+
25+
>>> r = requests.get("http://www.itdiffer.com")
26+
27+
得到一个请求的实例,然后:
28+
29+
>>> r.cookies
30+
<<class 'requests.cookies.RequestsCookieJar'>[]>
31+
32+
这个网站对客户端没有写任何cookies内容。换一个看看:
33+
34+
>>> r = requests.get("http://www.1world0x00.com")
35+
>>> r.cookies
36+
<<class 'requests.cookies.RequestsCookieJar'>[Cookie(version=0, name='PHPSESSID', value='buqj70k7f9rrg51emsvatveda2', port=None, port_specified=False, domain='www.1world0x00.com', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={}, rfc2109=False)]>
37+
38+
原来这样呀。继续,还有别的属性可以看看。
39+
40+
>>> r.headers
41+
{'x-powered-by': 'PHP/5.3.3', 'transfer-encoding': 'chunked', 'set-cookie': 'PHPSESSID=buqj70k7f9rrg51emsvatveda2; path=/', 'expires': '1981年11月19日 08:52:00 GMT', 'keep-alive': 'timeout=15, max=500', 'server': 'Apache/2.2.15 (CentOS)', 'connection': 'Keep-Alive', 'pragma': 'no-cache', 'cache-control': 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0', 'date': '2014年11月10日 01:39:03 GMT', 'content-type': 'text/html; charset=UTF-8', 'x-pingback': 'http://www.1world0x00.com/index.php/action/xmlrpc'}
42+
43+
>>> r.encoding
44+
'UTF-8'
45+
46+
>>> r.status_code
47+
200
48+
49+
下面这个比较长,是网页的内容,仅仅截取显示部分:
50+
51+
>>> print r.text
52+
53+
<!DOCTYPE html>
54+
<html lang="zh-CN">
55+
<head>
56+
<meta charset="utf-8">
57+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
58+
<title>1world0x00sec</title>
59+
<link rel="stylesheet" href="http://www.1world0x00.com/usr/themes/default/style.min.css">
60+
<link rel="canonical" href="http://www.1world0x00.com/" />
61+
<link rel="stylesheet" type="text/css" href="http://www.1world0x00.com/usr/plugins/CodeBox/css/codebox.css" />
62+
<meta name="description" content="爱生活,爱拉芳。不装逼还能做朋友。" />
63+
<meta name="keywords" content="php" />
64+
<link rel="pingback" href="http://www.1world0x00.com/index.php/action/xmlrpc" />
65+
66+
......
67+
68+
请求发出后,requests会基于http头部对相应的编码做出有根据的推测,当你访问r.text之时,requests会使用其推测的文本编码。你可以找出requests使用了什么编码,并且能够使用r.coding属性来改变它。
69+
70+
>>> r.content
71+
'\xef\xbb\xbf\xef\xbb\xbf<!DOCTYPE html>\n<html lang="zh-CN">\n <head>\n <meta charset="utf-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>1world0x00sec</title>\n <link rel="stylesheet" href="http://www.1world0x00.com/usr/themes/default/style.min.css">\n <link ......
72+
73+
以二进制的方式打开服务器并返回数据。
74+
75+
#post请求
76+
77+
requests发送post请求,通常你会想要发送一些编码为表单的数据——非常像一个html表单。要实现这个,只需要简单地传递一个字典给data参数。你的数据字典在发出请求时会自动编码为表单形式。
78+
79+
>>> import requests
80+
>>> payload = {"key1":"value1","key2":"value2"}
81+
>>> r = requests.post("http://httpbin.org/post")
82+
>>> r1 = requests.post("http://httpbin.org/post", data=payload)
83+
84+
r没有加data的请求,看看效果:
85+
86+
![](http://wxpictures.qiniudn.com/requets-post1.jpg)
87+
88+
r1是加了data的请求,看效果:
89+
90+
![](http://wxpictures.qiniudn.com/requets-post2.jpg)
91+
92+
多了form项。喵。
93+
94+
##http头部
95+
96+
>>> r.headers['content-type']
97+
'application/json'
98+
99+
注意,在引号里面的内容,不区分大小写`'CONTENT-TYPE'`也可以。
100+
101+
还能够自定义头部:
102+
103+
>>> r.headers['content-type'] = 'adad'
104+
>>> r.headers['content-type']
105+
'adad'
106+
107+
注意,当定制头部的时候,如果需要定制的项目有很多,需要用到数据类型为字典。
108+
109+
------
110+
111+
##老齐备注
112+
113+
网上有一个更为详细叙述有关requests模块的网页,可以参考:[http://requests-docs-cn.readthedocs.org/zh_CN/latest/index.html](http://requests-docs-cn.readthedocs.org/zh_CN/latest/index.html)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /