《零基础学Python》Python的HTML应用【十三】

整体文章目录

整体目录

一、 当前章节目录

在这里插入图片描述

二、HTML介绍

2.1 HTML的历史

  • HTML 1.0——在1993年6月作为互联网工程工作小组(IETF)工作草案发布(并非标准);
  • HTML 2.0——1995年11月作为RFC 1866发布,在RFC 2854于2000年6月发布之后被宣布已经过时 ;
  • HTML 3.2——1996年1月14日,W3C推荐标准 ; HTML 4.0——1997年12月18日,W3C推荐标准 ;
  • HTML 4.01——1999年12月24日,是在HTML4.0基础上的微小改进,W3C推荐标准 ;
  • HTML 5 的第一份正式草案已于2008年1月22日公布,仍继续完善。

2.2 SGML、HTML、XHTML、HTML5的关系

在这里插入图片描述

  • SGML:
    • 在 GML 的基础上进行整理,形成了一套非常严谨的文件描述方法。它的组成包括语法定义,DTD(W3C DTD 教程),文件实例三部分。
    • SGML是国际上定义电子文档和内容描述的标准。
    • SGML因太严谨规范达500多页,故而不易学、不易用、难以实现,所以在它的基础上又发展出了其他的更易用的
  • HTML:是人们抽取了 SGML的一个微小子集而提取出来的。其早期规范比较松散,但比较易学。
  • XHTML:它的出现是因为HTML扩充性不好,内容的表现跟不上时代的变化(如无法表示某些化学符号等),以及因为性能的问题,官方逐渐趋于严格的模式,所以使用 XML的严格规则的XHTML成了W3C 计划中 HTML 的替代者。
  • HTML5:
    • 经过一系列修订,到现在说的 HTML 一般指 HTML 4.01;
    • 而现在的 HTML 5则是 HTML 的第五个修订版,其主要的目标是将互联网语义化,以便更好地被人类和机器阅读,并同时提供更好地支持各种媒体的嵌入。
    • HTML5本身并非技术,而是标准。它所使用的技术早已很成熟,国内通常所说的html5实际上是html与css3及JavaScript和api等的一个组合,大概可以用以下公式说明:HTML5≈HTML+CSS3+JavaScript+API

2.3 HTML的标签

  • 结构性标签
  • 呈现性标签
  • 超文本链接标签
  • 框架页面标签

2.4 HTML的框架组成

<!DOCTYPE html>
<html>
	<head>
        <title>标题栏:第一个HTML页面</title>
    </head>
    <body>
        <h2>第一个HTML页面</h2>
        Hello,<b>World</b>
        <!-- 这是注释 -->
        <p>
            可以从
            <a href="http://www.w3c.org">W3C</a>
            网站上找到HTML的语言规范
        </p>
        <br>&copy;2019
    </body>
</html>

三、URL的处理

3.1 统一资源定位符

在这里插入图片描述

一种包含有授权的URL的语法如下:

协议://用户名@密码:子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数=值#标志

上面是一个比较完整的URL。一般URL都是在上面的基础上的一些简化,下面是一些URL示例。

  • http://www.w3.org/2005/10/Process-20051014/activities.html
  • ftp://ftp.test.com/pub/index.txt
  • first.html
    …/images/logo.jpg

3.2 URL的解析

在这里插入图片描述

In [1]: from urllib.parse import urlparse

In [2]: r = rlparse('http://alice:secret@www.hostname.com:80/%7Ealice/python.cgi?query=text#sample')
# 对URL进行解析

In [3]: r
Out[3]: ParseResult(scheme='http', netloc='alice:secret@www.hostname.com:80', path='/%7Ealice/python.cgi', params='', query='query=text', fragment='sample')

In [4]: r.scheme
Out[4]: 'http'

In [5]: r.netloc
Out[5]: 'alice:secret@www.hostname.com:80'

In [6]: r.path
Out[6]: '/%7Ealice/python.cgi'

In [7]: r.params
Out[7]: ''

In [8]: r.query
Out[8]: 'query=text'

In [9]: r.fragment
Out[9]: 'sample'

In [10]: r.username
Out[10]: 'alice'

In [11]: r.password
Out[11]: 'secret'

In [12]: r.hostname
Out[12]: 'www.hostname.com'

In [13]: r.port
Out[13]: 80

In [14]: r.geturl()
Out[14]: 'http://alice:secret@www.hostname.com:80/%7Ealice/python.cgi?query=text#sample'

In [15]: r2 = urlparse("www.python.org/about", "http")
# 使用了

In [16]: r2
Out[16]: ParseResult(scheme='http', netloc='', path='www.python.org/about', params='', query='', fragment='')

3.3 URL的拼合

In [1]: from urllib.parse import urljoin, urlsplit, urlunsplit
# 导入urljoin以及后面将使用的urlsplit、urlunsplit

In [2]: r = urljoin("http://www.zeroc.com", "ice.html")
# 将绝对URL和相对URL拼合

In [3]: r
Out[3]: 'http://www.zeroc.com/ice.html'

In [4]: r = urljoin("","")

In [5]: r
Out[5]: ''

In [6]: r = urljoin("http://www.python.org", "ftp://www.python.org/faq")

In [7]: r
Out[7]: 'ftp://www.python.org/faq'

In [8]: r = urljoin("http://www.python.org", "www.python.org/faq")

In [9]: r
Out[9]: 'http://www.python.org/www.python.org/faq'

In [10]: r = urljoin("http://www.python.org", "http://www.python.com/faq")

In [11]: r
Out[11]: 'http://www.python.com/faq'

3.4 URL的分解

In [1]: from urllib.parse import urljoin, urlsplit, urlunsplit

In [2]: r = urlsplit("http://python.org:80/faq.cgi?src=fie")

In [3]: r
Out[3]: SplitResult(scheme='http', netloc='python.org:80', path='/faq.cgi', query='src=fie', fragment='')

In [4]: r = urlunsplit(("http", "www.python.org", "faq", "", ""))

In [5]: r
Out[5]: 'http://www.python.org/faq'

In [6]: r = urlunsplit(urlsplit("http://www.python.org/faq?"))

In [7]: r
Out[7]: 'http://www.python.org/faq'
from urllib.parse import urlparse, urljoin, urlunsplit, urlsplit
abs_urls = ["http://www.python.org", "ftp://www.linux.org", "http://www.gtk.org", "file://"]
rel_url = "faq.html"

for abs_url in abs_urls:
    url = urljoin(abs_url, rel_url)     # 拼合URL
    expected_url = url
    scheme, netloc, path, query, fragment = urlsplit(url)       # 分解URL

    if scheme == "file":
        print(url, "====>None")
        continue

    if scheme is not "ftp":
        expected_url = urlunsplit(('http', netloc, path, query, fragment))
    print(url, "====>", expected_url)

运行结果:

http://www.python.org/faq.html ====> http://www.python.org/faq.html
ftp://www.linux.org/faq.html ====> http://www.linux.org/faq.html
http://www.gtk.org/faq.html ====> http://www.gtk.org/faq.html
file:///faq.html ====>None

3.5 URL的编解码

In [1]: from urllib.parse import quote, quote_plus, unquote, unquote_plus

In [2]: r1 = quote("/~test/")

In [3]: r1
Out[3]: '/~test/'

In [4]: r2 = quote("/~test/public html")

In [5]: r2
Out[5]: '/~test/public%20html'
# 空格被替换成%20

In [6]: r3 = quote_plus("/~test/public html")

In [7]: r3
Out[7]: '%2F~test%2Fpublic+html'

In [8]: unquote_plus(r3)
Out[8]: '/~test/public html'

In [9]: unquote(r2)
Out[9]: '/~test/public html'

In [10]: r = quote("/~test/", "~/")

In [11]: r
Out[11]: '/~test/'

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

3.6 中文的编解码

In [1]: from urllib.parse import quote, unquote

In [2]: quote("URL编码")
Out[2]: 'URL%E7%BC%96%E7%A0%81'
# 对URL进行编码

In [3]: r = quote("URL编码")

In [4]: unquote(r)
Out[4]: 'URL编码'
# 对URL进行解码

In [5]: print(unquote(r))
Out[5]: URL编码

In [6]: unquote("%E8%BF%99%E6%98%AF%E4%B8%80%E6%AE%B5%E7%A7%98%E5%AF%86%E7%9A%84%E6%B6%88%E6%81%AF")
Out[6]: '这是一段秘密的消息'

3.7 查询参数的编码

In [1]: from urllib.parse import urlencode
		import urllib
		import urllib.parse

In [2]: urlencode([('keyword1', 'value1'),('keyword2', 'value2')])
Out[2]: 'keyword1=value1&keyword2=value2'
# urlencode方法的作用就是将调查的参数值对返回成URL编码的形式

In [3]: urlencode({'keyword2':'value2','keyword1':'value1'})
Out[3]: 'keyword2=value2&keyword1=value1'

In [4]: a = {'keyword1':'value1', 'keyword2':'value2'}

In [5]: b = {'keyword2':'value2', 'keyword1':'value1'}

In [6]: a is b
Out[6]: False

In [7]: a == b
Out[7]: True

In [8]: urllib.parse.urlencode([('keyword',('value1', 'value2', 'value3'))])
Out[8]: 'keyword=%28%27value1%27%2C+%27value2%27%2C+%27value3%27%29'
# 默认为False,整个进行编码

In [9]: urllib.parse.urlencode([('keyword',('value1', 'value2', 'value3'))], True)
Out[9]: 'keyword=value1&keyword=value2&keyword=value3'
# 为True时,每个值都和keyword组成一个查询参数值对

In [10]: r = urlencode([('keyword', ('value1', 'value2', 'value3'))])

In [11]: urllib.parse.unquote_plus(r)
Out[11]: "keyword=('value1', 'value2', 'value3')"

四、CGI的使用

4.1 CGI介绍

#!C:\Users\86155\AppData\Local\Programs\Python\Python39\python.exe
# 指定执行cgi脚本文件的程序
# -*- coding: utf-8 -*-
print("Content-Type: text/html")
print()
print("Content-Type: text/html\n\n")
print('<!DOCTYPE html ">')
print('<html>')
print('<head>')
# 省略部分代码
print('<title>标题栏:第一个HTML页面</title>')
print('</head>')
print('<body>')
print('<h2>第一个HTML页面</h2>')
print('Hello,<b>World</b>')
print('<!-- 这是注释 -->')
print('<p>')
print('可以从')
print('<a href="http://www.w3c.org">W3C</a>')
print('网站上找到HTML的语言规范')
print('</p>')       
print('<br>&copy;2019')
print('</body>')
print('</html>')

运行结果:

在这里插入图片描述

在这里插入图片描述

4.2 获取CGI环境信息

#!C:\Users\86155\AppData\Local\Programs\Python\Python39\python.exe
# 指定执行cgi脚本文件的程序
# -*- coding: utf-8 -*-
print("Content-Type: text/plain\n\n")

import datetime
print(datetime.datetime.now())

运行结果:

这里是引用

#!C:\Users\86155\AppData\Local\Programs\Python\Python39\python.exe
# 指定执行cgi脚本文件的程序
# -*- coding: utf-8 -*-
import os
print("Content-Type: text/html\n\n")

remote_addr = os.environ['REMOTE_ADDR']

if remote_addr == '127.0.0.1':
    print("来自本地的访问")
else:
    print("来自外部的访问")

运行结果:

在这里插入图片描述

#!C:\Users\86155\AppData\Local\Programs\Python\Python39\python.exe
# 指定执行cgi脚本文件的程序
# -*- coding: utf-8 -*-
print("Content-Type: text/html\n\n")

import cgi

cgi.print_environ()

运行结果:

在这里插入图片描述

在这里插入图片描述

4.3 解析用户的输入

#!C:\Users\86155\AppData\Local\Programs\Python\Python39\python.exe
# 指定执行cgi脚本文件的程序
# -*- coding: utf-8 -*-
print("Content-Type: text/html\n\n")

import cgi
form = cgi.FieldStorage()

for key in form.keys():
    print(key, "==>", form[key].value)
    print("<br/>")

运行结果:

在这里插入图片描述
在这里插入图片描述

#!C:\Users\86155\AppData\Local\Programs\Python\Python39\python.exe
# 指定执行cgi脚本文件的程序
# -*- coding: utf-8 -*-
print("Content-Type: text/html\n\n")

import cgi
form = cgi.FieldStorage()

for key in form.keys():
    print(key, "==>", form.getlist(key))
    print("<br/>")

运行结果:

在这里插入图片描述
在这里插入图片描述

#!C:\Users\86155\AppData\Local\Programs\Python\Python39\python.exe
# 指定执行cgi脚本文件的程序
# -*- coding: utf-8 -*-
print("Content-Type: text/html\n\n")

import cgi
form = cgi.FieldStorage()

for key in form.keys():
    for value in form.getlist(key):
        print(key, "==>", cgi.escape(value))        # 使用escape()进行转义
        print("<br/>")

运行结果(需要显示出特殊字符,但是未调试出来,不知道原因):

在这里插入图片描述

五、获取HTML资源

5.1 使用urlopen和urlretrieve获取HTTP资源

In [1]: from urllib.request import urlopen

In [2]: r = urlopen("http://www.python.org")

In [3]: print(r.read())	# 输出读取的内容
Out[3]: # 见下图

在这里插入图片描述

from urllib.request import urlopen
fp = urlopen("http://www.python.org")

op = open("python.html", "wb")

n = 0
while True:
    s = fp.read(1024)
    if not s:       # 遇到了EOF
        break
    op.write(s)
    n = n + len(s)

fp.close()
op.close()

print("retrieved", n, "bytes from", fp.url)

运行结果:

retrieved 50126 bytes from https://www.python.org/
在这里插入图片描述

In [1]: from urllib.request import urlretrieve

In [2]: filename, m = urlretrieve("http://www.baidu.com")

In [3]: filename
Out[3]: 'C:\\Users\\86155\\AppData\\Local\\Temp\\tmpq4vco5dl'

In [4]: filename, m = urlretrieve("http://www.baidu.com", filename="D:/baidu.html")

In [5]: filename
Out[5]: 'D:/baidu.html'
In [1]: from urllib.request import urlretrieve

In [2]: def reporthook(block_count, block_size, file_size):
    		if file_size == -1:
        		print("retrieved data", block_count*block_size)
    		else:
        		print("retrieve data", block_count*block_size, "/", file_size)
        
In [3]: urlretrieve("http://www.python.org", filename="", reporthook = reporthook)
retrieve data 0 / 50807
retrieve data 8192 / 50807
retrieve data 16384 / 50807
retrieve data 24576 / 50807
retrieve data 32768 / 50807
retrieve data 40960 / 50807
retrieve data 49152 / 50807
retrieve data 57344 / 50807
Out[3]: ('C:\\Users\\86155\\AppData\\Local\\Temp\\tmpkduc697l',
 <http.client.HTTPMessage at 0x1e5f42067f0>)
 
In [4]: urlretrieve("http://www.google.cn", filename="", reporthook = reporthook)
retrieve data 0 / 1436
retrieve data 8192 / 1436
Out[4]: ('C:\\Users\\86155\\AppData\\Local\\Temp\\tmpiknw4w18',
 <http.client.HTTPMessage at 0x1e5f4206d90>)
from urllib.request import urlretrieve
def download(url, filename=""):
    def reporthook(block_count, block_size, file_size):
        if file_size == -1:
            print("Can't determine the file size, now retrieved", block_count*block_size)
        else:
            percentage = int((block_count*block_size*100.0)/file_size)
            if percentage > 100:
                print("100%")
            else:
                print("%d%%" % (percentage))
    filehandler, m = urlretrieve(url, filename, reporthook=reporthook)
    print("Done")
    return filehandler

if __name__ == '__main__':
    url = "https://www.baidu.com"
    print(download(url))

运行结果:

在这里插入图片描述
在这里插入图片描述

5.2 分析返回资源的相关信息

In [1]: from urllib.request import urlopen

In [2]: r = urlopen("http://baidu.com")

In [3]: r.geturl()
Out[3]: 'http://baidu.com'

In [4]: r.url
Out[4]: 'http://baidu.com'
In [1]: from urllib.request import urlopen

In [2]: r = urlopen("http://www.baidu.com")

In [3]: m = r.info()

In [4]: m.get_content_type()
Out[4]: 'text/html'

In [5]: m.get_content_maintype()
Out[5]: 'text'

In [6]: m.get_content_subtype()
Out[6]: 'html'

In [7]: m
Out[7]: <http.client.HTTPMessage at 0x145ab8b5e80>

In [8]: for k, v in r.info().items():
    		print (k, "=", v)
Bdpagetype = 1
Bdqid = 0x903d8eb8000225e3
Cache-Control = private
Content-Type = text/html;charset=utf-8
Date = Mon, 24 May 2021 01:08:59 GMT
Expires = Mon, 24 May 2021 01:08:31 GMT
P3p = CP=" OTI DSP COR IVA OUR IND COM "
P3p = CP=" OTI DSP COR IVA OUR IND COM "
Server = BWS/1.1
Set-Cookie = BAIDUID=7047AED9366C7DE11ED8072D2B784B65:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie = BIDUPSID=7047AED9366C7DE11ED8072D2B784B65; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie = PSTM=1621818539; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie = BAIDUID=7047AED9366C7DE190B9442796DA96A3:FG=1; max-age=31536000; expires=Tue, 24-May-22 01:08:59 GMT; domain=.baidu.com; path=/; version=1; comment=bd
Set-Cookie = BDSVRTM=0; path=/
Set-Cookie = BD_HOME=1; path=/
Set-Cookie = H_PS_PSSID=; path=/; domain=.baidu.com
Traceid = 1621818539028838759410393620435966240227
Vary = Accept-Encoding
Vary = Accept-Encoding
X-Ua-Compatible = IE=Edge,chrome=1
Connection = close
Transfer-Encoding = chunked

In [9]: r.headers
Out[9]: <http.client.HTTPMessage at 0x145ab8b5e80>

5.3 使用http.client模块获取资源

In [1]: import http.client	# 导入http.client模块
# 初始化三个https链接

In [2]: conn1 = http.client.HTTPSConnection("www.python.org")

In [3]: conn1.request("GET", "/doc/")	# 指定request请求的方法和请求的链接地址

In [4]: r1 = conn1.getresponse()

In [5]: print(r1.status, r1.reason)
Out[5]: 200 OK

In [6]: r1.read(256)
Out[6]: b'<!doctype html>\n<!--[if lt IE 7]>   <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9">   <![endif]-->\n<!--[if IE 7]>      <html class="no-js ie7 lt-ie8 lt-ie9">          <![endif]-->\n<!--[if IE 8]>      <html class="no-js ie8 lt-ie9">                 <![endif]-'

In [7]: conn1.close()

In [8]: conn1.request("GET", "/test.html")	# 请求一个不存在的文件或地址

In [9]: r2 = conn1.getresponse()

In [10]: print(r2.status, r2.reason)
Out[10]: 404 Not Found
In [11]: conn1.close()
In [12]: conn1.putrequest("GET", "/doc/")

In [13]: conn1.putheader("User-Agent", "Mozilla/4.0(compatible;MSIE 6.0;Windows NT 5.1)")

In [14]: conn1.putheader("Accept", "*/*")

In [15]: conn1.endheaders()

In [16]: r3 = conn1.getresponse()
200 OK

In [17]: print(r3.status, r3.reason)

In [18]: data3 = r3.read(256).decode()

In [19]: data3
Out[19]: '\n<!DOCTYPE html>\n<html lang="en">\n<head>\n  <meta http-equiv="content-type" content="text/html; charset=utf-8">\n  <meta name="robots" content="NONE,NOARCHIVE">\n  <title>403 Forbidden</title>\n  <style type="text/css">\n    html * { padding:0; margin:0; }\n    '

六、HTML文档的解析

from urllib.parse import urlparse, urljoin
from urllib.request import urlopen
from html import parser

class CheckHTML(parser.HTMLParser):         # 从HTMLParser类中继承
    available = True
    def handle_data(self, data):            # 定义处理数据的方法
        if "404 Not Found" in str(data) or "Error 404" in str(data):    # 当含有特定字符串的时候
            self.available = False

check_urls = ["/about/", "/blogs/", "/downloads/", "/faq/"]     # 需要检查的URL

for url in check_urls:
    new_url = urljoin("http://www.python.org/", url)        # 拼合URL
    try:
        fp = urlopen(new_url)           # 打开URL资源
        data = fp.read()                # 读取URL资源
        fp.close()
        p = CheckHTML()  # 生成一个CheckHTML类对象实例
        p.feed(str(data))  # 解析上面获得的数据
        p.close()
        # 判断URL是否存在
        if p.available:
            print(new_url, "==> OK")
    except:
        print(new_url, "==> Not Found")

运行结果:

http://www.python.org/about/ ==> OK
http://www.python.org/blogs/ ==> OK
http://www.python.org/downloads/ ==> OK
http://www.python.org/faq/ ==> Not Found

在这里插入图片描述

七、习题

习题:

  1. 什么是http协议?简单叙述http协议的连接过程。
  2. 解析https://www.python.org/,使用urllib抓取网页的内容,并打印出来。
  3. 根据示例代码练习相关库的使用。

答案:

  1. HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写。HTTP 协议和 TCP/IP 协议族内的其他众多的协议相同, 用于客户端和服务器之间的通信。请求访问文本或图像等资源的一端称为客户端, 而提供资源响应的一端称为服务器端。
    连接过程:如果从编程步骤上来讲,也就是套接字编程里面的步骤来说,需要先通过域名获得服务器的IP地址,调用相关的API可以完成这一步,然后需要将文本表示的IP地址转换为套接字编程要求的格式,然后端口号80也要转换成相应的格式,一般是一个结构体,然后建立套接字,调用connect函数就能建立连接了。
    2.代码如下。
from urllib.request import urlopen
fp = urlopen("http://www.python.org")

op = open("python.html", "wb")

n = 0
while True:
    s = fp.read(1024)
    if not s:       # 遇到了EOF
        break
    op.write(s)
    n = n + len(s)

fp.close()
op.close()

print("retrieved", n, "bytes from", fp.url)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值