Python练习

一、知识点

知识点1:Iterable和Iterator

|-------------------|-------------------------------------------|------------------------------------------|
| | 可迭代对象 Iterable | 迭代器 Iterator |
| 定义 | 可以一次返回其成员的对象,这意味着这些对象可以通过for...in循环进行遍历 | 是表示数据流的对象,通过重复调用迭代器的*next()*方法返回数据流中的连续项 |
| 核心方法 | iter() | iter()和__next__() |
| 获取方式 | 直接使用可迭代对象本身 | 通过对可迭代对象调用 iter()__iter__() 获得 |
| 状态 | 通常不保存迭代状态 | 保存当前的迭代状态(位置) |
| 遍历 | 不能直接使用 next() 遍历 | 可以使用 next() 逐个获取元素 |
| 遍历次数 | 可被多次遍历(每次创建新的迭代器) | 通常只能遍历一次(消耗型) |
| 示例类型 | 列表、元组、字符串、字典、集合 | iter(list) 返回的对象、生成器对象 |
| StopIteration | 不会直接引发 | 当元素耗尽时引发 StopIteration 异常 |

知识点2:map()和reduce()

python 复制代码
map() 函数:
1. 两个参数: function and Iterable
2. 作用: 将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回
3. 示例1: f(x)=x**2, 把f(x)作用到list[1,2,3,4,5,6,7,8,9],代码如下:
>>> def f(x):
        return x*x
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
4、示例2:把list[1,2,3,4,5,6,7,8,9]转换为字符串,代码如下:
>>> list(map(str,[1, 2, 3, 4, 5, 6, 7, 8, 9]))
['1', '2', '3', '4', '5', '6', '7', '8', '9']
python 复制代码
reduce()函数:
1、两个参数:function和iterable
2、作用:reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
3、示例1:对一个序列求和
>>> from functools import reduce
>>> def add(x, y):
        return x + y
>>> reduce(add, [1, 3, 5, 7])
16
4、str转换为int
>>> from functools import reduce
>>> def f(x, y):
        return x*10+y
>>> def strToInt(s):
        num = {'0':0, '1':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9}
        return num[s]
>>> reduce(f,map(strToInt,'1357'))
1357

相关练习:

1、利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']

python 复制代码
def f(name):
    return name[0].upper() + name[1:].lower()
print(list(map(f,['adam','LISA','barT'])))

2、请编写一个prod()函数,可以接受一个list并利用reduce()求积:

python 复制代码
from functools import reduce

def prod(x, y):
    return x * y

print('3 * 5 * 7 * 9 =', reduce(prod,[3, 5, 7, 9]))
if reduce(prod,[3, 5, 7, 9]) == 945:
    print('测试成功!')
else:
    print('测试失败!')

3、利用mapreduce编写一个str2float函数,把字符串'123.456'转换成浮点数123.456

python 复制代码
from functools import reduce
def strToInt(s):
    num = {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
    return num[s]

def f(x,y):
    return x*10+y

def str2float(s):
    return reduce(f,map(strToInt,s.split('.')[0]))+reduce(f,map(strToInt,s.split('.')[1]))/10**len(s.split('.')[1])

print('str2float(\'123.456\') =', str2float('123.456'))
if abs(str2float('123.456') - 123.456) < 0.00001:
    print('测试成功!')
else:
    print('测试失败!')

知识点3:filter()

python 复制代码
filter()函数:
1、两个参数:函数和序列
2、作用:过滤
3、示例:保留奇数
>>> def is_odd(n):
        return n % 2 == 1
>>> list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
[1, 5, 9, 15]

相关练习:

1、回数是指从左向右读和从右向左读都是一样的数,例如12321909。请利用filter()筛选出回数:

python 复制代码
def is_palindrome(n):
    s = str(n)
    return s == s[::-1]

# 测试:
output = filter(is_palindrome, range(1, 1000))
print('1~1000:', list(output))

知识点4:闭包

使用闭包,就是内层函数引用了外层函数的局部变量。如果只是读外层变量的值,我们会发现返回的闭包函数调用一切正常;但如果是对其赋值,则会把x当做函数counter()的局部变量

python 复制代码
def createCounter():
    x = 0
    def counter():
        nonlocal x
        x = x + 1
        return x
    return counter

# 测试:
counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5

知识点5:slots

通过__slots__来限制实例能添加的属性。

python 复制代码
class Student(object):
    __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称

s = Student() # 创建新的实例
s.name = 'Michael' # 绑定属性'name'
s.age = 25 # 绑定属性'age'
s.score = 99 # 绑定属性'score'    #报错:AttributeError: 'Student' object has no attribute 'score'

slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的。除非在子类中也定义__slots,这样,子类允许定义的属性就是自身的__slots__加上父类的__slots__。

python 复制代码
class Stu2(Stu):
    pass

ss=Stu2()
ss.name='bbb'
ss.age=21
ss.score=98
print(ss.score)    #输出:98

class Stu3(Stu):
    __slots__ = ('name','gender')

sss=Stu3()
sss.name='ccc'
sss.gender='m'
sss.age=20
print(sss.name)    #输出:ccc
print(sss.gender)    #输出:m
print(sss.age)    #输出:20

知识点6:@property

@property装饰器就是负责把一个方法变成属性调用的。

python 复制代码
class Screen(object):
    @property
    def width(self):
        return self.width
    @width.setter    #负责把该方法变成属性赋值
    def width(self, value):
        self._width = value
    @property
    def height(self):
        return self.height
    @height.setter
    def height(self, value):
        self._height = value

    @property    #只读属性,只定义getter方法,不定义setter方法就是一个只读属性
    def resolution(self):
        return self._width * self._height

# 测试:
s = Screen()
s.width = 1024
s.height = 768
print('resolution =', s.resolution)

知识点7:调试

错误信息:https://docs.python.org/3/library/exceptions.html#exception-hierarchy

1、print():把可能有问题的变量打印出来。

2、断言(assert):如果断言失败,assert语句本身就会抛出异常。(可通过-O参数关闭assert,如:python -O err.py)。

python 复制代码
def foo(s):
    n = int(s)
    assert n != 0, 'n is zero!'    #表达式n!=0应该是True,否则,后面代码出错。
    return 10 / n

def main():
    foo('0')

3、logging:和assert相比,logging不会抛出错误,而且可以输出到文件中。logging允许你指定记录信息的级别,有debug、info、warning、error等几个级别,当我们指定level=INFO时,其他级别的信息就不起作用了。这样一来,你可以放心地输出不同级别的信息,也不用删除,最后统一控制输出哪个级别的信息。另一个好处就是可以通过简单的配置,一条语句同时输出到不同的地方,如console和文件。

python 复制代码
import logging
logging.basicConfig(level=logging.INFO)

4、调试器pdb:让程序单步运行,可随时查看运行状态。

以参数 -m pdb 启动后,pdb定位到下一步要执行的代码;输入命令 l 查看代码;输入命令 n 单步执行代码;任何时候都可以输入命令 p 变量名 来查看变量;输入命令 q 结束调试,退出程序。

pdb.set_trace() #在可能出错的地方放一个,就可以设置一个断点,运行代码时,程序会自动在该语句暂停并进入pdb调试环境,可以使用命令p 来查看变量,或用命令 c 继续运行。

5、IDE:支持调试的IDE

知识点8:单元测试

对一个模块、一个函数或者一个类来进行正确性检验的测试工作。

编写单元测试时,我们需要编写一个测试类,从unittest.TestCase继承。

test开头的方法就是测试方法,不以test开头的方法不被认为是测试方法,测试的时候不会被执行。

对每一类测试都需要编写一个test_xxx()方法。由于unittest.TestCase提供了很多内置的条件判断,我们只需要调用这些方法就可以断言输出是否是我们所期望的。

python 复制代码
import unittest

class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score
    def get_grade(self):
        if self.score >= 60 and self.score < 80:
            return 'B'
        elif self.score >= 80 and self.score <= 100:
            return 'A'
        elif self.score < 0 or self.score > 100:
            raise ValueError
        return 'C'
class TestStudent(unittest.TestCase):

    def test_80_to_100(self):
        s1 = Student('Bart', 80)
        s2 = Student('Lisa', 100)
        self.assertEqual(s1.get_grade(), 'A')
        self.assertEqual(s2.get_grade(), 'A')

    def test_60_to_80(self):
        s1 = Student('Bart', 60)
        s2 = Student('Lisa', 79)
        self.assertEqual(s1.get_grade(), 'B')
        self.assertEqual(s2.get_grade(), 'B')

    def test_0_to_60(self):
        s1 = Student('Bart', 0)
        s2 = Student('Lisa', 59)
        self.assertEqual(s1.get_grade(), 'C')
        self.assertEqual(s2.get_grade(), 'C')

    def test_invalid(self):
        s1 = Student('Bart', -1)
        s2 = Student('Lisa', 101)
        with self.assertRaises(ValueError):
            s1.get_grade()
        with self.assertRaises(ValueError):
            s2.get_grade()

if __name__ == '__main__':
    unittest.main()

知识点9:正则表达式

在正则表达式中,如果直接给出字符,就是精确匹配。

search()方法用于在字符串中搜索正则表达式模式第一次出现的位置。

第一个参数是正则表达式模式,也就是你要描述的搜索规则。

找到后返回的范围是以下标0开始的。

python 复制代码
import re
re.search(r"Fish","I Love Fish!") 
<re.Match object; span=(7, 11), match='Fish'>

\d可以匹配一个数字

python 复制代码
>>> re.search(r'\d', 'I love 123 FishC.com!')
<re.Match object; span=(7, 8), match='1'>

\w可以匹配一个字母或数字

.可以匹配任意字符

python 复制代码
>>> re.search(r'.', 'I love FishC.com!')
<re.Match object; span=(0, 1), match='I'>
>>> re.search(r'co.', 'I love FishC.com!')
<re.Match object; span=(13, 16), match='com'>

反斜杠剥夺元字符(.)的特殊能力。

python 复制代码
>>> re.search(r'\.', 'I love FishC.com!')
<re.Match object; span=(12, 13), match='.'>

*表示任意个字符(包括0个)

+表示至少一个字符

?表示0个或1个字符

{n}表示n个字符

{n,m}表示n-m个字符:

  • '00\d'可以匹配'007',但无法匹配'00A'
  • '\d\d\d'可以匹配'010'
  • '\w\w\d'可以匹配'py3'
  • 'py.'可以匹配'pyc''pyo''py!'等等
  • eg:\d{3}\s+\d{3,8}
  1. \d{3}表示匹配3个数字,例如'010'
  2. \s可以匹配一个空格(也包括Tab等空白符),所以\s+表示至少有一个空格;
  3. \d{3,8}表示3-8个数字,例如'1234567'

要做更精确地匹配,可以用[]表示范围,比如:

0-9a-zA-Z\\_\]可以匹配一个数字、字母或者下划线; \[0-9a-zA-Z\\_\]+可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100','0_Z','Py3000'等等; \[a-zA-Z\\_\]\[0-9a-zA-Z\\_\]\*可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串,也就是Python合法的变量; \[a-zA-Z\\_\]\[0-9a-zA-Z\\_\]{0, 19}更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。 A\|B可以匹配A或B,所以(P\|p)ython可以匹配'Python'或者'python'。 \^表示行的开头,\^\\d表示必须以数字开头。 $表示行的结束,\\d$表示必须以数字结束。 使用 \[ \] 将任何内容包起来就是一个字符类,它的含义是你只要匹配这个字符类中的任何字符,结果就算作匹配。默认区分大小写。 ```python >>> re.search(r'[aeiou]', 'I love 123 FishC.com!') >>> re.search(r'[aeiouAEIOU]', 'I love 123 FishC.com!') >>> re.search(r'[a-z]', 'I love 123 FishC.com!') >>> re.search(r'[0-2][0-5][0-5]', 'I love 123 FishC.com!') # 重复匹配 >>> re.search(r'ab{3}c', 'abbbc') # 超过3个或者少于3个都不能匹配 >>> re.search(r'ab{3,5}c', 'abbbc') >>> re.search(r'ab{3,5}c', 'abbbbc') >>> re.search(r'ab{3,5}c', 'abbbbbc') ``` 用法: 正则表达式所有的元字符 . \^ $ \* + ? {} \[\] \\ \| () | 符号 | 含义 | |-------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | . | 表示匹配除了换行符外的任何字符。注:通过设置 re.DOTALL 标志可以使 . 匹配任何字符(包含换行符) | | \| | A \| B,表示匹配正则表达式 A 或者 B | | \^ | (脱字符)匹配输入字符串的开始位置。如果设置了 re.MULTILINE 标志,\^ 也匹配换行符之后的位置 | | $ | 匹配输入字符串的结束位置。如果设置了 re.MULTILINE 标志,$ 也匹配换行符之前的位置 | | \\ | 将一个普通字符变成特殊字符,例如 \\d 表示匹配所有十进制数字。 解除元字符的特殊功能,例如 . 表示匹配点号本身。引用序号对应的子组所匹配的字符串 | | \[...\] | 字符类,匹配所包含的任意一个字符。注:连字符 - 如果出现在字符串中间表示字符范围描述;如果出现在首位则仅作为普通字符。特殊字符仅有反斜线 \\ 保持特殊含义,用于转义字符。其它特殊字符如 \*、+、? 等均作为普通字符匹配。脱字符 \^ 如果出现在首位则表示匹配不包含其中的任意字符;如果 \^ 出现在字符串中间就仅作为普通字符匹配 | | {M,N} | M 和 N 均为非负整数,其中 M \<= N,表示前边的 RE 匹配 M \~ N 次。注:{M,} 表示至少匹配 M 次;{,N} 等价于 {0,N};{N} 表示需要匹配 N 次 | | \* | 匹配前面的子表达式零次或多次,等价于 {0,} | | + | 匹配前面的子表达式一次或多次,等价于 {1,} | | ? | 匹配前面的子表达式零次或一次,等价于 {0,1} | | \*?, +?, ?? | 默认情况下 *、+ 和 ? 的匹配模式是贪婪模式(即会尽可能多地匹配符合规则的字符串);*?、+? 和 ?? 表示启用对应的非贪婪模式。举个例子:对于字符串 "FishCCC",正则表达式 FishC+ 会匹配整个字符串,而 FishC+? 则匹配 "FishC" | | {M,N}? | 同上,启用非贪婪模式,即只匹配 M 次 | | (...) | 匹配圆括号中的正则表达式,或者指定一个子组的开始和结束位置。注:子组的内容可以在匹配之后被 \\数字 再次引用 。举个例子:(\\w+) \\1 可以字符串 "FishC FishC.com" 中的 "FishC FishC"(注意有空格) | | (?...) | (? 开头的表示为正则表达式的扩展语法(下边这些是 Python 支持的所有扩展语法) | | (?aiLmsux) | 1. (? 后可以紧跟着 'a','i','L','m','s','u','x' 中的一个或多个字符,只能在正则表达式的开头使用。2. 每一个字符对应一种匹配标志:re-A(只匹配 ASCII 字符),re-I(忽略大小写),re-L(区域设置),re-M(多行模式), re-S(. 匹配任何符号),re-X(详细表达式),包含这些字符将会影响整个正则表达式的规则。3. 当你不想通过 re.compile() 设置正则表达式标志,这种方法就非常有用啦。注意,由于 (?x) 决定正则表达式如何被解析,所以它应该总是被放在最前边(最多允许前边有空白符)。如果 (?x) 的前边是非空白字符,那么 (?x) 就发挥不了作用了 | | (?:...) | 非捕获组,即该子组匹配的字符串无法从后边获取 | | (?P\...) | 命名组,通过组的名字(name)即可访问到子组匹配的字符串 | | (?P=name) | 反向引用一个命名组,它匹配指定命名组匹配的任何内容 | | (?#...) | 注释,括号中的内容将被忽略 | | (?=...) | 前向肯定断言。如果当前包含的正则表达式(这里以 ... 表示)在当前位置成功匹配,则代表成功,否则失败。一旦该部分正则表达式被匹配引擎尝试过,就不会继续进行匹配了;剩下的模式在此断言开始的地方继续尝试。举个例子:love(?=FishC) 只匹配后边紧跟着 "FishC" 的字符串 "love" | | (?!...) | 前向否定断言。这跟前向肯定断言相反(不匹配则表示成功,匹配表示失败)。举个例子:FishC(?!.com) 只匹配后边不是 ".com" 的字符串 "FishC" | | (?\<=...) | 后向肯定断言。跟前向肯定断言一样,只是方向相反。举个例子:(?\<=love)FishC 只匹配前边紧跟着 "love" 的字符串 "FishC" | | (?\\|$) 是一个匹配邮件格式的正则表达式,可以匹配 [user@fishc.com](mailto:user@fishc.com) 和 '[user@fishc.com](mailto:user@fishc.com)',但是不会匹配 '\<[user@fishc.com](mailto:user@fishc.com)' 或 '[user@fishc.com](mailto:user@fishc.com)\>' | | \\ | 下边列举了由字符 '' 和另一个字符组成的特殊含义。注意,'' + 元字符的组合可以解除元字符的特殊功能 | | \\序号 | 1. 引用序号对应的子组所匹配的字符串,子组的序号从 1 开始计算。2. 如果序号是以 0 开头,或者 3 个数字的长度。那么不会被用于引用对应的子组,而是用于匹配八进制数字所表示的 ASCII 码值对应的字符。举个例子:(.+) \\1 会匹配 "FishC FishC" 或 "55 55",但不会匹配 "FishCFishC"(注意,因为子组后边还有一个空格) | | \\A | 匹配输入字符串的开始位置 | | \\Z | 匹配输入字符串的结束位置 | | \\b | 匹配一个单词边界,单词被定义为 Unidcode 的字母数字或下横线字符。举个例子:\\bFishC\\b 会匹配字符串 "love FishC"、FishC." 或 "(FishC)" | | \\B | 匹配非单词边界,其实就是与 \\b 相反。举个例子:py\\B 会匹配字符串 "python"、"py3" 或 "py2",但不会匹配 "py "、"py." 或 "py!" | | \\d | 1. 对于 Unicode(str 类型)模式:匹配任何一个数字,包括 \[0-9\] 和其他数字字符;如果开启了 re.ASCII 标志,就只匹配 \[0-9\]。2. 对于 8 位(bytes 类型)模式:匹配 \[0-9\] 中任何一个数字 | | \\D | 匹配任何非 Unicode 的数字,其实就是与 \\d 相反;如果开启了 re.ASCII 标志,则相当于匹配 \[\^0-9\] | | \\s | 1. 对于 Unicode(str 类型)模式:匹配 Unicode 中的空白字符(包括 \[ \\t\\n\\r\\f\\v\] 以及其他空白字符);如果开启了 re.ASCII 标志,就只匹配 \[ \\t\\n\\r\\f\\v\]。2. 对于 8 位(bytes 类型)模式:匹配 ASCII 中定义的空白字符,即 \[ \\t\\n\\r\\f\\v\] | | \\S | 匹配任何非 Unicode 中的空白字符,其实就是与 \\s 相反;如果开启了 re.ASCII 标志,则相当于匹配 \[\^ \\t\\n\\r\\f\\v\] | | \\w | 1. 对于 Unicode(str 类型)模式:匹配任何 Unicode 的单词字符,基本上所有语言的字符都可以匹配,当然也包括数字和下横线;如果开启了 re.ASCII 标志,就只匹配 \[a-zA-Z0-9_\]。2. 对于 8 位(bytes 类型)模式:匹配 ASCII 中定义的字母数字,即 \[a-zA-Z0-9_\] | | \\W | 匹配任何非 Unicode 的单词字符,其实就是与 \\w 相反;如果开启了 re.ASCII 标志,则相当于 \[\^a-zA-Z0-9_\] | | 转义符号 | 正则表达式还支持大部分 Python 字符串的转义符号:\\a,\\b,\\f,\\n,\\r,\\t,\\u,\\U,\\v,\\x,\\\\。注:\\b 通常用于匹配一个单词边界,只有在字符类中才表示"退格";\\u 和 \\U 只有在 Unicode 模式下才会被识别;八进制转义(\\数字)是有限制的,如果第一个数字是 0,或者如果有 3 个八进制数字,那么就被认为是八进制数;其他情况则被认为是子组引用;至于字符串,八进制转义总是最多只能是 3 个数字的长度 | ## 二、练习 ### **练习1** 请修改列表生成式,通过添加`if`语句保证列表生成式能正确地执行: ```python L1 = ['Hello', 'World', 18, 'Apple', None] L2 = [i.lower() for i in L1 if isinstance(i,str)] # 测试: print(L2) if L2 == ['hello', 'world', 'apple']: print('测试通过!') else: print('测试失败!') ``` ### 练习2 [杨辉三角](https://baike.baidu.com/item/%E6%9D%A8%E8%BE%89%E4%B8%89%E8%A7%92 "杨辉三角")定义如下: 1 / \ 1 1 / \ / \ 1 2 1 / \ / \ / \ 1 3 3 1 / \ / \ / \ / \ 1 4 6 4 1 / \ / \ / \ / \ / \ 1 5 10 10 5 1 把每一行看做一个list,试写一个generator,不断输出下一行的list: ```python def triangles(): t=[1] while True: yield t t=[t[i-1]+t[i] if i>0 else t[i] for i in range(len(t))]+[1] pass # 期待输出: # [1] # [1, 1] # [1, 2, 1] # [1, 3, 3, 1] # [1, 4, 6, 4, 1] # [1, 5, 10, 10, 5, 1] # [1, 6, 15, 20, 15, 6, 1] # [1, 7, 21, 35, 35, 21, 7, 1] # [1, 8, 28, 56, 70, 56, 28, 8, 1] # [1, 9, 36, 84, 126, 126, 84, 36, 9, 1] n = 0 results = [] for t in triangles(): results.append(t) n = n + 1 if n == 10: break for t in results: print(t) if results == [ [1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1], [1, 5, 10, 10, 5, 1], [1, 6, 15, 20, 15, 6, 1], [1, 7, 21, 35, 35, 21, 7, 1], [1, 8, 28, 56, 70, 56, 28, 8, 1], [1, 9, 36, 84, 126, 126, 84, 36, 9, 1] ]: print('测试通过!') else: print('测试失败!') ``` ### 练习3 把`Student`的`gender`属性改造为枚举类型 ```python from enum import Enum, unique @unique class Gender(Enum): Male = 0 Female = 1 class Student(object): def __init__(self, name, gender): self.name = name self.gender = gender # 测试: bart = Student('Bart', Gender(0)) if bart.gender == Gender.Male: print('测试通过!') else: print('测试失败!') ``` ## 三、实践 1、下载一张图像 urllib.request用于打开和读取URL ```python import urllib.request rep = urllib.request.urlopen("http://placecats.com/louie/300/300") cat_img = rep.read() with open('D:\Desktop\cat_300_300.jpg','wb') as f: f.write(cat_img) ``` 2、用有道来翻译文本 urllib.parse用于解析URL 所有来自URL解析函数的返回值都会提供encode()方法和decode()方法。 ```python import urllib.request import urllib.parse import json content = input("请输入需要翻译的内容:") url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=http://www.youdao.com" data = {} data['type'] = 'AUTO' data['i'] = content data['doctype'] = 'json' data['version'] = '2.1' data['keyfrom'] = 'fanyi.web' data['ue'] = 'UTF-8' data['typoResult'] = 'true' data = urllib.parse.urlencode(data).encode('utf-8') # 转换格式并编码为utf-8 response = urllib.request.urlopen(url, data) # post请求必须带上data参数 html = response.read().decode('utf-8') target = json.loads(html) print("翻译结果:%s" % (target['translateResult'][0][0]['tgt'])) # 一层一层剥掉 ``` 设置headers参数有两种方法: * 实例化Request参数时将headers参数传进去 ```python import urllib.request import urllib.parse import json content = input("请输入需要翻译的内容:") url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=http://www.youdao.com" head = {} head['Referer'] = 'http://fanyi.youdao.com/' head['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' data = {} data['type'] = 'AUTO' data['i'] = content data['doctype'] = 'json' data['version'] = '2.1' data['keyfrom'] = 'fanyi.web' data['ue'] = 'UTF-8' data['typoResult'] = 'true' data = urllib.parse.urlencode(data).encode('utf-8') req = urllib.request.Request(url, data, headers=head) response = urllib.request.urlopen(req) html = response.read().decode('utf-8') target = json.loads(html) print("翻译结果:%s" % (target['translateResult'][0][0]['tgt'])) print(req.headers) ``` * 通过add_header()方法往Request对象添加headers ```python import urllib.request import urllib.parse import json content = input("请输入需要翻译的内容:") url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=http://www.youdao.com" data = {} data['type'] = 'AUTO' data['i'] = content data['doctype'] = 'json' data['version'] = '2.1' data['keyfrom'] = 'fanyi.web' data['ue'] = 'UTF-8' data['typoResult'] = 'true' data = urllib.parse.urlencode(data).encode('utf-8') req = urllib.request.Request(url, data) req.add_header('Referer', 'http://fanyi.youdao.com') req.add_header('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36') response = urllib.request.urlopen(req) html = response.read().decode('utf-8') target = json.loads(html) print("翻译结果:%s" % (target['translateResult'][0][0]['tgt'])) print(req.headers) ``` 如果同一IP在短时间内对服务器频繁访问,一旦超过服务器设置的访问频率,就会返回一个验证码页面,爬虫就不能正常获取信息,所以被拒绝,可通过以下两种方法解决: * 延迟提交的时间 * 使用代理 3、

相关推荐
我可以将你更新哟2 小时前
【爬虫】爬取斗罗大陆漫画,面向对象封装(存入数据库)
数据库·爬虫·python
Macbethad2 小时前
Jenkins自动化持续集成技术报告
开发语言
麦麦大数据2 小时前
F060 基于BERTvue+flask电影评论情感分析系统
后端·python·flask·bert·推荐算法·情感分析·电影评论
yongche_shi2 小时前
第八十九篇:CAP理论、BASE理论在系统设计中的应用
开发语言·python·面试宝典·cap理论·base理论
CoderCodingNo2 小时前
【GESP】C++五级真题(数论、埃氏筛思想考点) luogu-B3969 [GESP202403 五级] B-smooth 数
开发语言·c++·算法
BD_Marathon2 小时前
Claude Code概述
java·开发语言
沐知全栈开发2 小时前
jQuery CSS 类
开发语言
golang学习记2 小时前
[特殊字符] Go Gin 不停机重启指南:让服务在“洗澡搓背”中无缝升级
开发语言·golang·gin
这周也會开心2 小时前
Collections和Arrays工具类整理
java·开发语言