鱼C论坛

 找回密码
 立即注册
楼主: BigSmall

[学习笔记] 课堂笔记-从3开始

[复制链接]
 楼主| 发表于 2018-11-4 14:48:12 | 显示全部楼层
本帖最后由 BigSmall 于 2018-11-5 11:17 编辑

43
工厂函数就是类对象
len()和dir()是BIF
而int()、list()和我们之前定义的类,这些都是工厂函数,即类对象(type)

int()里面的加减方法可以被修改,加法变减法,或者变成其他的

有关算术的魔法方法



44
Python 魔法方法详解
https://fishc.com.cn/forum.php?mod=viewthread&tid=48793&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403


#43和44都是讲算术运算的,所以这里将他们写在一块,还有一个重要的原因跳过了45课。


小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-4 16:01:50 | 显示全部楼层
本帖最后由 BigSmall 于 2018-11-6 21:53 编辑

45
简单定制
定制一个计时器的类


准备:

使用time模块的localtime方法获取两个时间,然后时间相减,就会得到时间间隔
localtime输出的格式不太好理解(会很麻烦),所以就改用time.time()函数
time模块详解:https://fishc.com.cn/forum.php?mod=viewthread&tid=51326&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403

__str__:如果要把一个类的实例变成 str,就需要实现特殊方法__str__(),就是类实例化后就是一个字符串,类里面通过return函数返回字符串
__repr__:类实例化后直接打印一个字符串


代码:

timer1.0:相当好理解,里面有很多bug,具体优化见timer2.0
import time as t

class Mytimer():
    #计时开始
    def start(self):
        self.starttime=t.time() #这里time.time()函数是将现在的时间转换成秒(从1970年开始算),小数点后还有好几位
        print('计时开始')
        
    #计时结束
    def stop(self):
        self.stoptime=t.time()
        print('计时结束')
        
    #计算时间间隔
    def count(self):
        self.duringtime=int(self.stoptime-self.starttime) #之前说了,这里小数点后有好几位,所以用了int转换成整数
        print('运行了'+str(self.duringtime)+'s')




timer2.0:优化了bug
import time as t #注意我们这里将time模块用t来表示,如果在后面的运行的时候,实例化的时候如果名字是t,就会出问题,尽量使实例化的名字不要跟我们写的程序代码一样

class Mytimer():
    def __init__(self):
        self.duringtime='未开始计时' #如果开始就直接调用t1,就显示'未开始计时',没有这句就会报错;如果属性的名字与函数的名字一样,那么函数就会被属性替换
        self.starttime=0 #为后的if语句服务
   
    def __repr__(self): #repr函数是将实例化的类转化成字符串,并打印出来;这里是当直接输入t1,那么就会直接输出多少秒,不用执行count函才输出,或者是执行stop函数就会输出
        return(self.duringtime)

    def __add__(self,other):
        self.totaltime='一共运行了'+str(int(self.stoptime-self.starttime+other.stoptime-other.starttime))+'s' #之前这里我还是用的self.duringtime,因为我还是想的不return,直接repr打印,可是不行
        return(self.totaltime) #这里为什么非得用return呢?因为你在写t1+t2时,看到+,会直接调用t1的__add__,所以必须return;而我们一般用的+,就是算术的直接加,这里是特殊的,不能直接加
   
    #计时开始
    def start(self):
        self.starttime=t.time()
        print('计时开始')
        self.duringtime='未结束计时' #这个是当运行了start函数,如果输入t1,那么会提醒你;运行t1打印的是self.duringtime,这里提前给self.duringtime赋值了
        
    #计时结束
    def stop(self):
        if not self.starttime: #当not self.duringtime不等于0(即self.duringtime=0),那么就没有经过start的赋值语句,说明没有计时
            print('未开始计时')
        else:
            self.stoptime=t.time()
            print('计时结束')
            self.count() #在函数里面可以直接调用函数的另一个函数,写法就是这里的self.函数名();调用该函数就不需要再调用count函数了,直接进行计算
        
    #计算时间间隔
    def count(self):
        self.duringtime='运行了'+str(int(self.stoptime-self.starttime))+'s' #这里为什么都用字符串呢,因为repr函数只会打印字符串,所以在这里强制转换了
        #本来这里有个print,可是有了repr函数,就不需要了;repr直接调用,比之前的调用count函数更符合计时器
      
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-4 17:11:58 | 显示全部楼层
本帖最后由 BigSmall 于 2018-11-5 10:47 编辑

46
之前学的是魔法方法来改变一些函数方法,这节课是改变属性

第一个例子:
class C:
    def __init__(self,size=10):
        self.size=size
    def getSize(self):
        return self.size
    def setSize(self,value):
        self.size=value
    def delSize(self):
        del self.size
    x=property(getSize,setSize,delSize)
接下来,c.x会直接调用getSize;c.x=1会直接调用setSize;del c.x会调用delSize

这是因为这些set还有get之类的方法都是描述符,根据你的操作实现对应功能。下面那个列子也一样

第二个例子:
class Test:
    def __init__(self,width=0,height=0):
        self.width=width
        self.height=height

    def __setattr__(self,name,value):
        if name=='a':
            self.width=value
            self.height=value
        else:
            self.name=value
__setattr__这个是设置属性,每当有self的属性进行赋值操作时,就会被调用
操作:
test1=Test(1,2)
这就会陷入无限的循环,首先__init__里面width赋值操作,setattr被调用,name是width,不是a,执行else-self.name赋值操作,继续调用setattr,所以无限循环
修正:
将self里面的self.name=value改为super().__setattr__(name,value),意思一样,就是防止了无限循环
到else时,name不是a,就为name赋值value,即为width赋值width
然后init里面的height赋值,继续调用setattr,后面的就同上了

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-5 08:14:24 | 显示全部楼层
本帖最后由 BigSmall 于 2018-11-5 10:47 编辑

47
描述符
描述符就是 将某种特殊类型的类的实例指派给另一个类的属性。简单的说就是在一个新类里面放入实例化的特殊类。
有关的魔法方法有以下三种:
__get__(self,instance,owner):
用于访问属性,它返回属性的值。
__set__(self,instance,value):
将在属性分配操作中调用,不返回任何内容。
__delete__(self,instance):
控制删除操作,不返回任何内容。
所谓特殊类型的类,就是含有以上三种魔法方法的类。然后把这个特殊的类的实例,指派给另一个类的属性

对于特殊类型的类,进行赋值操作,暂且认为先__init__有了初值,然后__set__设置了新值

温度华氏度与摄氏度之间的转换
class Sheshidu:
    def __init__(self,value=26):#__init__函数不写也可以执行set,但是get无法传入value,而且必须为value赋初值,否则__init__执行不下去
        self.value=float(value)#float是为了转换时出现小数
    def __get__(self,instance,owner):#模板写法
        return(self.value)
    def __set__(self,instance,value):#模板写法
        self.value=float(value)

class Huashidu:
    def __get__(self,instance,owner):
        return(instance.shishidu*1.8+23)#在华氏度与摄氏度之间建立关系,通过输入摄氏度转换成华氏度,instance实现两个特殊类的关联
                                                       #输入wendu.shishidu=1,此时进入shishidu的get,然后输入wendu.huashidu,进入huashidu的get,再进入instance.shishidu,这样就实现了转换
    def __set__(self,instance,value):
        instance.shishidu=(float(value)-32)/1.8#在华氏度与摄氏度之间建立关系,通过输入华氏度转换成摄氏度,实现原理如上

class Wendu:
    shishidu=Sheshidu()
    huashidu=Huashidu()
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-5 10:43:33 | 显示全部楼层
本帖最后由 BigSmall 于 2018-11-5 10:53 编辑
BigSmall 发表于 2018-11-5 08:14
47
描述符
描述符就是 将某种特殊类型的类的实例指派给另一个类的属性。简单的说就是在一个新类里面放入 ...


47课课后习题
https://www.jianshu.com/p/d3b41de6a91a


#以后有什么补充内容还是修改写入帖子里面吧,写在回复里面不方便看
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-7 08:48:53 | 显示全部楼层
本帖最后由 BigSmall 于 2018-11-7 19:56 编辑

48
定制容器
协议:一种指南
诸如列表、元组和字典,这些都是容器,里面存放各种各样的对象

容器类型的协议:
如果你定制的容器不可变,如元组、字符串,你只需要定义__len__()和__getitem__()方法
如果你希望定制的容器是可变的,除了上述两种方法外,还需要定义__setitem__()和__delitem__()方法

容器类型的魔法方法
__len__(self):定义当被 len() 调用时的行为(返回容器中元素的个数)
__getitem__(self, key):定义获取容器中指定元素的行为,相当于 self[key](返回列表元素,并实现你需要的功能)
__setitem__(self, key, value):定义设置容器中指定元素的行为,相当于 self[key] = value
__delitem__(self, key):定义删除容器中指定元素的行为,相当于 del self[key]
__iter__(self):定义当迭代容器中的元素的行为
__reversed__(self):定义当被 reversed() 调用时的行为
__contains__(self, item):定义当使用成员测试运算符(in 或 not in)时的行为


练习:编写一个不可改变的自定义列表,要求记录列表中每个元素被访问的次数
      准备:1.*args:(表示的就是将实参中按照位置传值,多出来的值都给args,且以元祖的方式呈现)
                        def foo(x,*args):
                                    print(x)
                                    print(args)
                        foo(1,2,3,4,5)        #其中的2,3,4,5都给了args
                        1
                        (2, 3, 4, 5)                #这里args其实是一个元组
                2.列表推导式提供了一种创建list的简便方法。应用程序创建列表时,列表中的元素来源于其他序列、可迭代对象或创建的一个满足一定条件的序列。
                self.values=[x for x in args]                #其实就是创建了elf.values这个列表,列表里面的元素是x,x是for循环遍历元组args
                3.统计每个元素被访问的次数,最先想到的是什么,是字典,将这个列表的下标作为这个字典的键,它的值就是它对应的访问次数
                4.字典的创建:{}.fromkeys(包含键的列表,键的初值)
                5.range(3)就是创建一个列表[0,1,2]

               
               




小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-7 20:25:47 | 显示全部楼层
本帖最后由 BigSmall 于 2018-11-8 16:11 编辑

48课后题
0.首先,序列是是Python中最基本的数据结构。序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推。每个索引对应一个元素。
字典不是序列,他是python中唯一的一个映射类型
4.容器的一些操作:读 —— __getitem__(),写 —— __setitem__(),删除 —— __delitem__()
5.在 Python 中,协议更像是一种指南。这有点像我们之前在课后作业中提到的“鸭子类型”(忘了的朋友请戳:http://bbs.fishc.com/thread-51471-1-1.html) —— 当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。Python就是这样,并不会严格地要求你一定要怎样去做,而是让你靠着自觉和经验把事情做好!所以python就没那么正式。

return之后的语句不会被执行



0.定制一个列表,同样要求记录列表中每个元素被访问的次数
要求1:实现获取、设置和删除一个元素的行为(删除一个元素的时候对应的计数器也会被删除)
要求2:增加 counter(index) 方法,返回 index 参数所指定的元素记录的访问次数
要求3:实现 append()、pop()、remove()、insert()、clear() 和 reverse() 方法(重写这些方法的时候注意考虑计数器的对应改变)
自己写的,比较笨,看不懂答案里面的super()。#这里我们用list2表示实例化后的列表
class Mylist:
    def __init__(self,*args):               
        self.newlist=[x for x in args]
        self.countlist=[0 for x in args]
#init就是准备工作,这里要定制一个列表,要求记录列表中每个元素被访问的次数。想法就是用两个列表,一个来存放元素,一个来返回元素被访问的次数。

    def __repr__(self):
        return str(self.newlist)
#repr,运行的时候当输入list2(实例化的)的时候,可以直接返回想要的列表,这里我们newlist是存放元素的,所以这里我们返回这个

    def __len__(self):
        return len(self.newlist)

    def __getitem__(self,listkey):
        self.countlist[listkey]+=1
        return self.newlist[listkey]
#get函数就是读,比如我们输入list2[1]时,表示我们读取list2中位置1的元素,此时list2[1]就被访问一次,访问次数加一

    def __setitem__(self,listkey,value):
        self.countlist[listkey]+=1
        self.newlist[listkey]=value
#set就是写,就是将列表中某个位置的元素重写,此时也算访问一次

    def __delitem__(self,listkey):
        del self.newlist[listkey]
        del self.countlist[listkey]
#del就是删除,我们这里不仅要删除元素,而且还要删除元素对应的访问次数
#因为我们写的newlist就是一个列表,delitem函数的实现就是要删除newlist与countlist,那就直接调用这两个列表的del函数就可以了,即del self.countlist[listkey]

    def counter(self,listkey):
        return self.countlist[listkey]
#上面三个函数的实现都是直接调用的,不用‘列表名.方法’这样来调用,但是之后的就不一样了

    def append(self,value):
        self.countlist.append(0)
        self.newlist.append(value)

    def pop(self,listkey):
        print(self.newlist[listkey])        #这里为什么用print,因为return实现不了
        del self.newlist[listkey]
        del self.countlist[listkey]

    def remove(self,value):
        key=self.newlist.index(value)       
        del self.newlist[key]
        del self.countlist[key]

    def insert(self,listkey,value):
        self.newlist.insert(listkey,value)
        self.countlist.insert(listkey,0)

    def clear(self):
        self.newlist.clear()
        self.countlist.clear()

    def reverse(self):
        self.newlist.reverse()
        self.countlist.reverse()
   
        
        

   
        
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-7 20:44:42 | 显示全部楼层
本帖最后由 BigSmall 于 2018-11-12 19:44 编辑

49迭代器
迭代就是重复一个操作
递归就是自己调用自己

列表、元组、字符串都是可迭代对象
for i in 序列


diedaiqi1=iter(可迭代对象);生成迭代器
next(diedaiqi1);比如字符串,会依次返回字符串的值
如果迭代到没有元素,那就会报错;StopIteration

两个魔法方法:
__iter__();返回本身
__next__();迭代要实现的内容
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-11-8 19:19:22 | 显示全部楼层
楼主每天在哪看课程学习的,看小甲鱼的零基础入门学py?还是b站上的视频?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-10 14:48:34 | 显示全部楼层
ssxx43 发表于 2018-11-8 19:19
楼主每天在哪看课程学习的,看小甲鱼的零基础入门学py?还是b站上的视频?

在b站上看小甲鱼
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-12 20:15:40 | 显示全部楼层
本帖最后由 BigSmall 于 2018-11-13 13:53 编辑

50生成器
生成器仅需要普通的函数就可以实现。生成器是迭代器的一种实现,迭代器需要我们定义一个类,而生成器只要在简单的函数里面加上yield语句。
yield相当于一个return,执行到yield返回值并跳出函数,下一次迭代直接运行之后的内容

协同程序就是可以运行的独立函数调用,函数可以暂停或者挂起,并在需要的时候从程序离开的地方继续或者重新开始

用for语句执行迭代器,可以识别StopIteration,当执行到StopIteration直接退出循环

(推导式)是生成器推导式;e=(i%2==0),此时e就是一个生成器,执行的就是打印能整除2的数

扩展阅读;https://fishc.com.cn/forum.php?mod=viewthread&tid=56023&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403



小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-12 20:40:23 | 显示全部楼层
51模块
模块就是更高级的封装

封装:
容器-数据的封装;列表,元组,字符床,字典
函数-语句的封装
类-方法和属性的封装,也就是对函数和数据的封装
模块-程序;也就是我们写的.py文件,模块要和你要import的文件放在同一目录

命名空间:程序.函数

%后跟.2;意思就是保留小数点后两位小数

导入模块
import 模块名;调用的时候需要模块名.函数名
from 模块名 import 函数名;调用的时候直接函数名
from 模块名 import *;导入所有的函数,不推荐这么做,名字混乱,文件自身的和模块里面名字相同的会被覆盖
import 模块名 as 新名字;最推荐的


  
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-12 21:09:20 | 显示全部楼层
52模块

模块里面可以调用自己的函数,这样运行就会直接执行该函数,通常测试函数这么做
if __name__== '__main__';就是有些函数(测试函数)不希望出现在其他函数的调用中,就在模块中将调用函数的的语句写在if __name__== '__main__'里面,这样就只会出现在该模块的执行中

搜索路径:python有自己默认的路径,它会在默认的路径里面搜索模块,一般推介放在’site-packages‘里卖弄,不过我们也可以将我们需要的路径添加到默认的路径里面。sys.path.append("添加路径")
,这里sys.path是默认的路径,是一个列表。

包;就是整理模块
第一步,创建一个文件加,用于存放相关的模块,文件夹的名字即包的名字
第二步,在包文件夹中创建一个__init__.py的模块文件,内容可以为空
第三步,将相关的模块放到该文件夹中
导入的时候,包名.模块名

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-12 21:44:53 | 显示全部楼层
53
不开心,不小心点了发帖,之前记的本节课的笔记也丢失了,21:44,算了,明天再说吧
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-13 12:50:03 | 显示全部楼层
本帖最后由 BigSmall 于 2018-11-13 13:55 编辑

53像个极客一样去思考

使用现成的模块来工作
python标准库有数百个模块

打开python文档;idle-help-python docs

与计算机相关的单词语法;每天学一点英语

模块社区;http://pypi.python.org/pypi

如何独立的探索模块
计时器模块-timeit
helip-索引timeit;需要阅读长篇的英文资料
idle-import timeit-timeit.__all__(all精简完就是可以供外界调用的所有信息)
time.__flie__,源代码位置
help(timeit);复杂度介于中间的方法

timeit文档翻译;https://fishc.com.cn/forum.php?mod=viewthread&tid=55593&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-15 21:41:46 | 显示全部楼层
本帖最后由 BigSmall 于 2018-12-7 21:47 编辑

54论一只爬虫的自我修养

python如何访问互联网
urllib
url;就是平常说的网页地址
url的一般格式;协议://域名(有时候要包含端口号,即:端口号)/路径
端口号;协议都有默认的端口号,http的默认端口为80
协议有http、https、ftp、file、ed2k
urllib其实是一个包,里面有四个模块

urllib.request模块;urlopen(字符串)函数访问网页

例子:
import urllib.request as a
b=a.urlopen('网站地址')
c=b.read()
print(c)
c=decode('utf-8')
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-18 19:33:29 | 显示全部楼层
本帖最后由 BigSmall 于 2018-12-7 21:59 编辑

55实战


例1
import urllib.request as req                #导入访问网页的模块
i=400

while i<=1000:
    a='https://placekitten.com/'+str(i)+'/'+str(i)
    cat=req.urlopen(a)                #访问网页
    cat_pic=cat.read()                #读取网页,并赋值给cat_pic(值是二进制的)
    with open ('cat'+str(i)+'.jpg','wb') as f:                #创建一个cat.jpg的文件类f(二进制的写)
        f.write(cat_pic)                #将二进制的值写入f类
    i+=50
注意;这里‘’里面是不能直接写变量的,需要将变量str


例2
Network标签页
Network标签页对于分析网站请求的网络情况、查看某一请求的请求头和响应头还有响应内容很有用,特别是在查看Ajax类请求的时候,非常有帮助。注意是在你打开Chrome开发者工具后发起的请求,才会在这里显示的哦。
点击左侧某一个具体去请求URL,可以看到该请求的详细HTTP请求情况:
我们可以在这里看到HTTP请求头、HTTP响应头、HTTP返回的内容等信息,对于开发、调试,都是很有用的。
简单地说,就是当网页运行的时候,客户端发出请求,然后服务器执行的方法和内容

方法中的get和post都可以向服务器提交数据
点开方法,preview中可以查看是否实现了想要的功能,headers中可以查看方法实现的具体内容

request是网络请求
request header是发出请求的客户端,其中的user agent可以查看你是用什么系统、什么软件访问的,很多网页拒绝非人类访问,就是在这里监察访问的软件。但是这样依然阻挡不了我们代码访问,这里的user agent是可以进行修改的。

form date是表张数据,就是post方法提交的主要的内容
python的urlopen(url字符串,date);date默认的是get方法,要是需要的话可以传入值,改为post方法。但是date是有特定的格式的,这里我们可以用函数urllib.parse.urlencode()来将字符串或者字典转换成这个格式。而且urllib.parse.urlencode()这个函数是在urllib包里面的独立的模块urllib.parse
urlencode默认的是Unicode,有时候需要encode为utf-8编码形式;encode(utf-8)。相对的,如果你想将utf-8的编码转为Unicode的形式;decode(utf-8)
如果对编码还有什么问题的话,https://fishc.com.cn/forum.php?mod=viewthread&tid=56452&highlight=python%B1%E0%C2%EB%CE%CA%CC%E2(Python编码问题的解决方案总结)

文本类型中有一种是json的格式,json模块中的json.loads()可以将这种格式的文本转换成字典或则列表什么的。

urllib.request.urlopen(url,date)

翻译编码:
import urllib.request
import urllib.parse
import json

xuyaofanyideneirong=input('需要翻译的内容:')

fangwenwangye='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
date={}
date['i']=xuyaofanyideneirong
date['from']='AUTO'
date['to']='AUTO'
date['smartresult']='dict'
date['client']='fanyideskweb'
date['salt']='1542554407027'
date['sign']='13b4b3afa475edda17f39ac5aac4acc6'
date['doctype']='json'
date['version']='2.1'
date['keyfrom']='fanyi.web'
date['action']='FY_BY_REALTIME'
date['typoResult']='false'
fanyifangfa=urllib.parse.urlencode(date).encode('utf-8')

wangyefanyifangfafangwen=urllib.request.urlopen(fangwenwangye,fanyifangfa)
wangyefanyifangfaduqu=wangyefanyifangfafangwen.read().decode('utf-8')
zifuchuanzhuanweizidian=json.loads(wangyefanyifangfaduqu)
fanyijieguo=zifuchuanzhuanweizidian['translateResult'][0][0]['tgt']

print('翻译结果为:%s'%fanyijieguo)




小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-19 16:45:19 | 显示全部楼层
本帖最后由 BigSmall 于 2018-12-7 21:36 编辑

56隐藏
一般网站掐掉不正常的网站访问,为了使我们的程序能够持续的干活,那么我们需要对代码进行隐藏,让它看成是正常的网站访问。
服务器检查访问地址是检查headers里面的user-agent,来判断你是来自代码还是来自浏览器。
urllib.request.Request(url,date=None,headers={});通过修改headers可以设置新的headers,headers必须是一个字典;两种方法,一种是直接设置一个字典,写入Request的参数,另外一种是Request.add_header()。

代码
import urllib.request
import urllib.parse
import json
import time

while True:
    content=input('需要翻译的内容(break退出):')
    if content=='break':
        break

    url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
    head={}
    head['User-Agent']='Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'

    date={}
    date['i']=content
    date['from']='AUTO'
    date['to']='AUTO'
    date['smartresult']='dict'
    date['client']='fanyideskweb'
    date['salt']='1542554407027'
    date['sign']='13b4b3afa475edda17f39ac5aac4acc6'
    date['doctype']='json'
    date['version']='2.1'
    date['keyfrom']='fanyi.web'
    date['action']='FY_BY_REALTIME'
    date['typoResult']='false'
    date=urllib.parse.urlencode(date).encode('utf-8')

    req=urllib.request.Request(url,date,head)                #不同于上一节的直接实例化打开,这里先实例化req,然后加head参数,只有Request可以加head参数。或者这句后面加req.add_header()
    html=response.read().decode('utf-8')
    target=json.loads(html)
    target=target['translateResult'][0][0]['tgt']

    print('翻译结果为:%s'%target)

    time.sleep(5)



修改了header就可以了吗?并不行,一个爬虫一秒钟下载上百张图片,对服务器的压力很大,所以服务器会对访问过多的地址设置验证码,阻止爬虫。对于这种限制,有两种策略:一是延迟提交的时间(例如上面的代码),另一种是使用代理,用很多个代理发起访问(具体分析如下)。
代理的步骤:
1,设置一个代理网站ip的字典
2,定制一个opener,当我们打开网页的时候就是默认opener在工作,opener可指定headers或者指定ip地址来访问
3,安装opener;安装之后就可以一直使用了
4,如果只有在特殊的时候才调用opener,那我们就用opener.open(url)函数来调用

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-12-8 14:20:50 | 显示全部楼层
略微感觉有些迷茫啊,搞什么也搞不下去
没人指导,自己学太慢、太累
前几天搞了几天科研,搞不出来啊,过来放松几天吧
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-12-8 14:23:13 | 显示全部楼层
57
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-23 07:40

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表