Django之自定义反爬虫功能

来自CloudWiki
跳转至: 导航搜索

技术要点

1)识别请求来自浏览器还是来自爬虫程序,根据不同的访问方式给出不同的响应。

2)获取客户端IP地址并限制其访问时间间隔,如果来自爬虫程序,则多次访问之间的间隔会很短,判断这种情况并给出相应的响应。

3)使用自定义修饰器实现代码复用。

实现形式

修改views文件

修改questions应用的views.py文件,导入time标准库中的time()函数,并定义修饰器函数isCraw()。

from time import time#用来记录当前时间的函数
ips = [None]  #用来存储客户端最后一次访问的IP地址
last = 0 #存储客户端最后一次访问时间
def isCraw(func):
    def wrapper(*args,**kwargs):
        global ips,last  #声明全局变量
        agent = args[0].META.get('HTTP_USER_AGENT')
        #获得请求的头部信息
        if 'Mozilla' not in agent /#不是浏览器
        and 'Safari' not in agent /
        and 'Chrome' not in agent:
            return HttpResponse('禁止使用爬虫')
        else:
            ip = args[0].META.get('REMOTE_ADDR')
            #客户端ip地址
            now = time()
            if ip==ips[0] and now-last<5:
                #距离上次访问不超过5秒
                return HttpResponse('禁止使用爬虫')
            last = now
            ips.pop()
            ips.append(ip)#更新客户端最后一次访问时间和IP地址
            return func(*args,**kwargs)
    return wrapper

添加修饰器

把定义的修饰器作用到相应的视图函数上,以登录界面为例。

@isCraw
def login(request):
    #退出登录
    request.session = {}
    try:
        #获取网页参数,用户名和密码
        account = request.POST['usr']        
        password  = hashlib.md5(request.POST['pwd'].encode()).hexdigest()
        #验证用户名和密码
        users = Students.objects.filter(account=account,password=password)
        
        if users :
            #登陆成功后添加session信息            
            request.session['account'] = account
                    
            #页面跳转
            return redirect('/check/')
        else:
            return render(request,'login.html',{'msg':'用户名或密码不正确'})
    except:
        return render(request,'login.html',{'msg':None}

运行网站

执行命令,运行网站,使用浏览器打开登录界面,一切正常。

Python9-12.png

编写爬虫

使用Python模块urllib编写简单爬虫程序,尝试读取登录界面信息,失败。

>>> url = r'http://127.0.0.1:8000/check/login/'
>>> import urllib.request
>>> with urllib.request.urlopen(url) as fp:
	print(fp.read().decode())

Python10-9.png

修改爬虫

修改程序,伪装浏览器访问登录页面,成功。

>>> url = r'http://127.0.0.1:8000/check/login/'
>>> import urllib.request
>>> headers = {'user-agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64)AppleWobKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36'}
>>> req = urllib.request.Request(url=url,headers=headers)
>>> with urllib.request.urlopen(req) as fp:
	print(fp.read().decode())


Python10-10.png

进一步修改爬虫

进一步修改爬虫程序,连续多次读取登录页面,第一次成功,后面失败。

url = r'http://127.0.0.1:8000/check/login/'
import urllib.request
headers = {'user-agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64)AppleWobKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36'}
for i in range(5):
    req = urllib.request.Request(url=url,headers=headers)
    with urllib.request.urlopen(req) as fp:
        print(fp.read().decode())
    

Python10-11.png