练习41:学着去说面向对象

一 词汇训练

  • 类(class):告诉python创建一个新类型的东西。(Tell python to make a new type of thing).
  • 对象(object):两种含义:最基本类型的东西,任何实例。(the most basic type of thing,and any instance of something)。
  • 实例(instance):当你告诉python创建一个类的时候你所得到的东西。(What you get when you tell pythong to create a class).
  • def:你如何在类里面定义一个函数。(How you define a function inside a class)。
  • self:在一个类的函数里面,self是被访问的实例/对象的一个变量。(inside the functions in a class,self is a variable for the instance/object being accessed)。
  • 继承(inheritance):关于一个类能从另一个类那里继承它的特征的概念,很像你和你的父母。(The concept that one class can inhert traits from other class,much like you and your parents)。
  • 组合(composition):关于一个类可以由其它一些类构成的概念,很像一辆车包含几个轮子。(The concept that a class can be composed of other classes as parts,much like how a car has wheels)。
  • 属性(attribute):类所拥有的从组合那里得到的特性,通常是变量。(A property classes have that are from composition and are usually variables)。
  • is-a:一种用来表达某物继承自一种东西的表述,就像“三文鱼是一种鱼”。(A phrase to say that something are from inherits from another,as in a "salmon" is a "fish")
  • has-a:一种用来表达某物是由一些东西组成或具有某种特性的表述,就像“三文鱼有一个嘴巴。”(A phrase to say that something is composed of other things or has a trait,as in "a salmon has-a mouth.")

二 短语训练

  • class X(Y) :创建一个名为 X 并继承自 Y 的类。(“Make a class named X that is-a Y.”)
  • class X(object): def __init__(self, J):类 X 有一个带有 self 和 J 参数的 __init__ 函数。(“class X has-a __init__ that takes self and J parameters.”)
  • class X(object): def M(self, J) :类 X 有一个带有 self 和 J 参数的 M 函数。(“class X has-a function named M that takes self and J parameters.”)
  • foo = X() :设 foo 为类 X 的一个实例。(“Set foo to an instance of class X.”)
  • foo.M(J)  从 foo 那里获取 M 函数,并用 self 和 J 参数来调用它。(“From foo, get the M function, and call it with parameters self, J.”)
  • foo.K = Q  从 foo 那里获取 K 属性,并设它为 Q。(“From foo, get the K attribute, and set it to Q.”)

三 代码

1 urllib标准库

  • 网络爬虫简介:
    • 定义:按照一定规则,自动抓取万维网信息的程序或脚本。
    • 两大特征:
      • 能按程序员要求下载数据或者内容
      • 能自动在网络上流窜(从一个网页跳转到另一个网页)
    • 两大步骤:
      • 下载网页
      • 提取正确的信息
      • 根据一定规则自动跳转其它撤销页面上执行以上两步操作
    • 爬虫分类:
      • 通用爬虫(常见的搜索引擎)
      • 专用爬虫(聚集爬虫)
    • python常用的网络包:
      • Python3:urllib、requests
  • urllib库:
    • 是什么:urllib是python内置的处理HTTP请求的库
    • 有什么:主要包含以下四个模块
      • urllib.request 请求模块:它是最基本的 HTTP 请求模块,我们可以用它来模拟发送一请求,就像在浏览器里输入网址然后敲击回车一样,只需要给库方法传入 URL 还有额外的参数,就可以模拟实现这个过程了。
      • urllib.error 异常处理模块:如果出现请求错误,我们可以捕获这些异常,然后进行重试或其他操作保证程序不会意外终止。
      • urllib.parse url解析模块: parse 模块是一个工具模块,提供了许多 URL 处理方法,比如拆分、解析、合并等等的方法。
      • urllib.robotparser robots.txt解析模块:主要是用来识别网站的 robots.txt 文件,然后判断哪些网站可以爬,哪些网站不可以爬的,其实用的比较少。
  • urllib.request.urlopen函数:
    • 功能:用于实现对目标url的访问。
    • 函数原型:urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
    • 参数介绍:一般常用的有三个——url,data,timeout
      •  url 参数:目标资源在网路中的位置。可以是一个表示URL的字符串(如:https://www.boxuegu.com);也可以是一个urllib.request对象。
      • data参数:data用来指明发往服务器请求中的额外的参数信息(如:在线翻译,在线答题等提交的内容),HTTP是python中实现的众多网络通信http、https、ftp等协议中,唯一一个 使用data 参数的,也就是说只有打开的是http网址的时候,自定义data参数才会有作用。
        • data必须是一个字节数据对象(Python的bytes object)
        • data必须符合标准the standard application/x-www-form-urlencoded format,怎么得到这种标准结构的data呢?使用urllib.parse.urlencode()将自定义的data转换成标准格式,而这个函数所能接收的参数类型是pyhon中的mapping object(键/值对,如dict) or a sequence of two-element tuples(元素是tuple的列表)。
        • data也可以是一个可迭代的对象,这种情况下就需要配置response对象中的Conten-length,指明data的大小。
        • data默认是None,此时以GET方式发送请求;当用户给出data参数的时候,改为POST方式发送请求。
      • timeout参数:设置超时时间,单位是秒。
        • 如果请求超过这个时间还没有得到响应,就会抛出异常。如果没有设定的话,就会使用全局的默认时间。支持HTTP,HTTPS,FTP!
        • 我们可以设置超时时间来控制网页爬取时间超过规定时间就跳出,使用try except语句是实现。
      • context参数:实现SSL加密传输。(基本上很少用)
      • cafile、capath参数:是指定 CA 证书和它的路径,这个在请求 HTTPS 链接时会有用。(基本很少用)
      • cadefault 参数现在已经弃用了,默认为 False。
    • urlopen返回对象提供方法:
      • read() , readline() ,readlines() , fileno() , close() :对HTTPResponse类型数据进行操作
      • info():返回HTTPMessage对象,表示远程服务器返回的头信息
      • getcode():返回Http状态码。如果是http请求,200请求成功完成;404网址未找到
      • geturl():返回请求的url
    • 版本区别:python2和python3在导入urlrequest的方式是不一样的。
      • python2中:import urllib2
      • python3里面把urllib分开了,分成了urlrequest和urlerror,在这里我们只需导入urlrequest即可。from urllib.request import urlopen
  • Request类
    • 功能:urlopen()可以实现简单的请求,但是它无法添加一些header信息,也就不能构建一个完整的请求。所以我们可以用Request类来构建一个完整的请求。
    • 函数原型:class urlib.request.Request(url,data=None,headers={},origin_req_host=None,unverifiable=False,method=None)
    • 参数介绍:
      • url:请求的url ,必传参数。
      • data: 类型是bytes类型,如果是字典,使用urllib.parse中的urlencode()编码!
      • headers:参数是一个字典,表示请求的请求标识和载体!可以在构造 Request 时通过 headers 参数直接构造,也可以通过调用Request实例的add_header()方法来添加。 Request Headers 最常用的用法就是通过修改 User-Agent 来伪装浏览器,默认的 User-Agent 是 Python-urllib,我们可以通过修改它来伪装浏览器。
      • origin_host:表示请求的host名称或者IP地址。
      • unverifiable:参数表示这个请求是否是无法验证的,默认是False.意思就是说用户没有足够权限来选择接收这个请求的结果。例如我们请求一个 HTML 文档中的图片,但是我们没有自动抓取图像的权限,这时 unverifiable 的值就是 True。
      • method:是一个字符串,它用来指示请求使用的方法,比如GET,POST,PUT等等。
  • 异常处理:
    • 功能:urllib 的error模块定义了由request模块产生的异常。如果出现了问题,request模块就会抛出error模块中定义的异常!
    • 两个常见的异常:URLError,HTTPError,HTTPError是URLError的子类
      • URLError里只有一个属性:reason,即抓异常的时候只能打印错误信息
      • HTTPError里有三个属性:code,reason,headers,即抓异常的时候可以获得code,reson,headers三个信息
        • code,返回 HTTP Status Code,即状态码,比如 404 网页不存在,500 服务器内部错误等等。
        • reason,同父类一样,返回错误的原因。
        • headers,返回 Request Headers。
      • 因为 URLError 是 HTTPError 的父类,所以我们可以先选择捕获子类的错误,再去捕获父类的错误
  • Url解析:
    • urlparse()
      • 功能:对你传入的url地址按特定的协议类型进行拆分
      • 原型:urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)
        • urlstring:url地址参数
        • scheme:指定协议类型,如果url里面已经带了协议,再通过scheme指定的协议就不会生效
    • urlunpars():用于拼接
    • urljoin():也用做拼接
    • urlencode():可以将字典转换为url参数
  • 参考内容:

2 random模块

  • 功能:用于生成随机数
  • 常见方法:
    • random.random():生成一个随机的浮点数,范围是在0.0~1.0之间
    • random.uniform(a,b) :用于生成一个指定范围内的随机符点数,两个参数其中一个是上限,一个是下限。如果a > b,则生成的随机数n: b <= n <= a。如果 a <b, 则 a <= n <= b。
    • random.randint(a, b):用于生成一个指定范围内的整数。其中参数a是下限,参数b是上限,生成的随机数n: a <= n <= b
    • random.randrange([start], stop[, step]):从指定范围内,按指定基数递增的集合中 获取一个随机数。
    • random.choice(sequence):可以从任何序列,比如list列表中,选取一个随机的元素返回,可以用于字符串、列表、元组等。
    • random.shuffle(x[, random]):原地指定seq序列,用于将一个列表中的元素打乱,即将列表内的元素随机排列。
    • random.sample(sequence, k):从指定序列中随机获取指定长度的片断并随机排列。注意:sample函数不会修改原有序列。

2 代码

它所做的事情就是用一个叫做 urllib 的图书馆来下载一列单词。
 1 import random                                      # 导入random模块
 2 from urllib.request import urlopen                 # 导入urllib库中的urlopen方法
 3 import sys                                         # 导入sys模块
 4 
 5 WORD_URL = "http://learncodethehardway.org/words.txt"       # 保存要访问的网页地址Url
 6 WORDS = []
 7 
 8 PHRASES = {
 9     "class %%%(%%%):":
10         "Make a class named %%% that is-a %%%.",
11     "class %%%(object):\n\tdef __init__(self,***)":
12         "class %%% has-a __init__ that takes self and *** params.",
13     "class %%%(object):\n\tdef ***(self,@@@)":
14         "class %%% has-a function *** that takes self and @@@ params.",
15     "*** = %%%()":
16             "Set *** to an instance of class %%%.",
17     "***.***(@@@)":
18             "From *** get the *** function,call it with params self @@@.",
19     "***.*** = '***'":
20             "From *** get the *** attribute and set it to '***'."
21 }                                                          # 存储类、函数、方法的定义或者调用格式
22 
23 # do they want to drill phrases first
24 if len(sys.argv) == 2 and sys.argv[1] == "english":        # 如果命令行参数有两个,且第二个参数是english,即在执行过程中命令行参数必须有两个,第一个是脚本文件名,第二个是english
25     PHRASE_FIRST = True                                    # PHRASE_FIRST值为True
26 else:
27     PHRASE_FIRST = False                                   # 否则PHRASE_FIRST值为False
28 
29 # load up the words from the website
30 for word in urlopen(WORD_URL).readlines():                 # 打开WORD_URL对应的网页地址,并返回有每行内容组成的列表(会保存在硬盘中),再通过for循环遍历得到的列表
31     WORDS.append(str(word.strip(),encoding="utf-8"))       # 去除每行的头尾空白后,将其转换成字符串,并采用utf-8格式编码,将编码后的内容添加到列表WORDS中
32 
33 def convert(snippet,phrase):                               # 将字典的键和值中的特殊符号和从WORDS_URL中读到的内容进行替换
34     class_names = [w.capitalize() for w in                 # 利用for循环遍历的到的随机列表,并将列表元素字符串中的第一个字母变大写,其它字母变小写
35                                                            # snippet.count()表示统计PHARSES字典的键里面某个字符串出现的次数,即为伪装一个类名或其它内容需要的单词的个数
36     random.sample(WORDS,snippet.count("%%%"))]             # 通过分片的方式从列表WORDS中得到长度为snippet.count("%%%")的列表,然后将分片得到的列表内部元素随机排列
37     other_names = random.sample(WORDS,snippet.count("***"))# 通过分片的方式从列表WORDS中得到长度为snippet.count("***")的列表,然后将分片得到的列表内部元素随机排列
38     results = []
39     param_names = []
40     
41     for i in range(0,snippet.count("@@@")):
42         param_count = random.randint(1,3)                  # 利用random.randint()函数产生一个1、2、3中的随机整数,控制分片后列表的长度
43         param_names.append(','.join(                       # 用","将分片后得到的列表的内容连接成字符串
44             random.sample(WORDS,param_count)))             # 利用param_count将WORDS列表分片,然后将分片得到的列表内部元素随机排列
45     
46     for sentence in snippet,phrase:                        # 用sentence遍历PHRASES字典的键和值
47         result = sentence[:]                               # 利用切片操作完成对sentence列表的复制
48         
49         # fake class names                                 # 伪装类名称
50         for word in class_names:
51             result = result.replace("%%%",word,1)          # 将result中的字符串"%%%"用class_names中得到的word代替,替换不超过一次
52         
53         # fake other names                                 # 伪装函数或方法等其它内容的名称
54         for word in other_names:
55             result = result.replace("***",word,1)          # 将result中的字符串"***"用other_names中得到的word代替,替换不超过一次
56         
57         # fake parameter lists                             # 伪装参数列表
58         for word in param_names:
59             result = result.replace("@@@",word,1)          # 将result中的字符串"@@@"用param_names中得到的word代替,替换不超过一次
60         
61         results.append(result)                             # 将result添加到列表results当中,并返回results列表的值
62     return results
63 
64 # keep going until they hit CTRL-D
65 try:                                                       # 异常
66     while True:
67         snippets = list(PHRASES.keys())                    # snippets是由PHRASES字典的键组成的列表
68         random.shuffle(snippets)                           # 将snippets列表中的元素顺序打乱
69         
70         for snippet in snippets:                           # 遍历snippets列表
71             phrase = PHRASES[snippet]                      # 通过键snippet对应的值
72             question,answer = convert(snippet,phrase)      # 调用convert函数,完成键值对中字符串的替换,并将函数返回值
73             if PHRASE_FIRST:                               # 
74                 question,answer = answer,question          # 将替换后的结果与问题换过来
75             
76             print(question)                                # 打印question,表示经过替换的PHRASES字典的键的内容
77             
78             input("> ")                                    # 可输入answer中提示的内容来查看对应的类或者方法的结构
79             print(f"ANSWER:{answer}\n\n")                  # 打印answer,即question键对应的经过替换的PHRASES字典的值的内容
80 except EOFError:
81     print("\nBye")

执行过程中,输入:

1 python oop_test.py english
有关字符串的内容,可参考:https://www.cnblogs.com/luoxun/p/13257881.html
 
posted @ 2020-07-29 19:53  洛兰123  阅读(213)  评论(0编辑  收藏  举报