zoukankan      html  css  js  c++  java
  • 反爬虫

    反爬虫

    反爬虫:就是使用任何技术手段阻止批量获取网站信息的方式;其实我们做的就是了解反爬虫的技术,继而反反爬虫。

    反爬虫的方式

    (1)不返回网页;

    • 网站通过ip访问量反爬虫,对访问进行统计,单个ip访问量超过阈值,则封杀或者输验证码;
    • 通过session(会话控制)访问量反爬虫,session对象存储用户会话所需属性和配置信息,用户在web页跳转,存储在session中变量不会丢失,而是在整个会话中一直存下去,如果一个session的访问量过大,就会进行封杀或者输验证码;
    • 通过User-Agent反爬虫,当用requests库进行爬虫,默认的User-Agen为python-requests/(xxx),服务器判断其不是真正的浏览器会予以封杀;

    (2)返回非目标网页,如返回错误页、空白页、同一页;
    (3)增加获取难度,如登录及验证码、12306登陆选图片;

    反反爬虫

    (1) 修改请求头
    如果不修改请求头,网页默认为python-requests/xxx,所以需要修改;也可以做一个User-Agen 的池,但针对User-Agen的访问量进行封锁的不多,一般设置为正常的浏览器的user-Agen就好了。

    # encoding:utf-8
    
    import requests;
    link='http://www.santostang.com/';
    r=requests.get(link);
    print (r.request.headers);
    
    headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'};
    r=requests.get(link,headers=headers);
    print (r.request.headers);
    

    headers,修改前后对比:

    (2)修改爬虫的间隔时间

    • 爬虫过于频密,对网站很不友好,或者导致网站的反爬虫。可以使用time 库在爬虫访问之间设置一定的间隔时间
    t1=time.time();
    print ('t1: ',t1);
    time.sleep(2);
    t2=time.time();
    print ('t2: ',t2);
    t=t2-t1;
    print ('t2-t1: ',t);
    

    加入间隔时间:

    • 加入随机的时间,使用一个固定的数字作为时间间隔,不像正常用户的行为,可以使用random库进行随机数设置;random.randint(0,2)的结果是0/1/2,andom.random()是0~1的随机数,相加获得更随意的sleep时间。
    t1=time.time();
    print ('t1: ',t1);
    sleep_time=random.randint(0,2)+random.random();
    time.sleep(sleep_time);
    t2=time.time();
    print ('t2: ',t2);
    print (sleep_time);
    

    运行两次,两次sleep时间不一样,如图

    • 爬取网页过程中,加入sleep time,在两次爬虫中添加一定的时间间隔。例如爬取http://www.santostang.com/中多个子网页中的文章题目,考虑到进入子网页也需要爬取该子网页,所以将网页爬取部分封装成函数。
    # encoding:utf-8
    import requests;
    from bs4 import BeautifulSoup;
    import time,random;
    def scarp_url(link):
        headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'};
        r=requests.get(link,headers=headers);
        soup=BeautifulSoup(r.text);
        return soup;
    
    link='http://www.santostang.com/';#主网页
    soup=scarp_url(link);
    post_titles=soup.find_all('h1',class_='post-title');
    for each in post_titles:
        title_link=each.a['href'];#进入到具体的博客文章中
        print ("休息一下");
        sleep_time=random.randint(0,2)+random.random();
        time.sleep(sleep_time);
        t1=time.time();
        print ("爬取子网页前时间:",t1);
    
        print ("开始爬取具体博客子网页");
        soup_title=scarp_url(title_link);
        title=soup_title.find('h1',class_='view-title').text.strip();
        print ("这篇博客名:",title);
        t2=time.time();
        print ("爬取子网页后时间:",t2);
    

    将sleep放在每一个网页更改前,红框中以爬取两个但还是出现错误ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。 是服务器为了维护自己的安全,对于不正常的浏览网页者做的限制。刚开始不知http://www.santostang.com/是否是网页的问题,因为该网址有网页进入不了。所以更换了一个网址(豆瓣),重新测试。

    import requests;
    from bs4 import BeautifulSoup;
    import time,random;
    
    def scarp_url(link):
        headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'};
        r=requests.get(link,headers=headers);
        soup=BeautifulSoup(r.text);
        return soup;
    
    link='https://book.douban.com/tag/%E5%B0%8F%E8%AF%B4';#主网页
    soup=scarp_url(link);
    post_titles=soup.find_all('li',class_='subject-item');
    for each in post_titles:
        info_url=each.find('div',class_='info');
        title_link=info_url.a['href'];#子网页的地址
        print (title_link);·
    
        print ("休息一下");
        sleep_time=random.randint(0,2)+random.random();
        time.sleep(sleep_time);
        t1=time.time();
        print ("爬取子网页前时间:",t1);
    
        print ("开始爬取具体豆瓣具体书本的子网页");
        soup_title=scarp_url(title_link);
        title=soup_title.find('span',property='v:itemreviewed').text.strip();
        print ("这书本名:",title);
        t2=time.time();
        print ("爬取子网页后时间:",t2);
    

    爬取结果,是ok的,所以前面一个网页自己的问题哦;但目前还不知道 遇到这种网页应该怎么办。

    • 其实时间sleep 可以放在更换网页切换之间,其实很随意。当然也可以不用每次换网页就休息,可以在每次爬取间隔少点,但是多次爬取后再休息多一点时间,比较符合正常浏览的习惯;
    def scarp_url(link):
        headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'};
        r=requests.get(link,headers=headers);
        soup=BeautifulSoup(r.text);
        return soup;
    
    link='https://book.douban.com/tag/%E5%B0%8F%E8%AF%B4';#主网页
    soup=scarp_url(link);
    post_titles=soup.find_all('li',class_='subject-item');
    
    scrap_time=0; #计算爬取次数
    for each in post_titles:
        info_url=each.find('div',class_='info');
        title_link=info_url.a['href'];
        print (title_link);
    
        print ("开始爬取具体豆瓣具体书本的子网页");
        soup_title=scarp_url(title_link);
        title=soup_title.find('span',property='v:itemreviewed').text.strip();
        print ("这书本名:",title);
        t2=time.time();
        print ("爬取子网页后时间:",t2);
    
        scrap_time+=1;
        if scrap_time % 5==0:
            sleep_time=10+random.random();
        else:
            sleep_time=random.randint(0,2)+random.random();
        time.sleep(sleep_time);
        t1=time.time();
        print ("爬取子网页前时间:",t1);
    

    增加一个scrap 次数计数。

    (3)使用代理

    代理是一种特殊的网络服务,允许一个网络终端(一般为客户端),通过这个服务于另一个网络终端(一般为服务器)进行非直接的连接,其实就是信息的中转站。比如,直接访问国外的网站速度很慢,就可以用国内的代理服务器中转,数据先从国外某网站到国外的代理服务器,再到计算机,反而会比较快。

    因此在爬虫过程中,可以维护一个代理池,让自己的爬虫程序隐藏自己的真实ip。但是代理ip池较难维护,且不稳定。使用代理ip获取网页的方法,模板如下:

    import requests;
    link='http://www.santostang.com/';
    proxies={'http':'http://xxx.xxxxx.xxxxx',...};#就是多个IP地址的字典
    response=requests.get(link,proxies=proxies);
    

    NOTE

    • 代理池,具体没有试过。但应该就是在request.get()中,加个代理池的参数吧。后期用到再查资料吧。
    • 反反爬,可以从headers和sleep中,估计可以搞定蛮多平时的练习网站了吧。
    • 听说后面还有更换ip、处理登陆表单和验证码。后面入坑再说吧。
  • 相关阅读:
    编写高质量Python代码的59个有效方法
    排序NB三人组(快速排序/堆排序/归并排序)
    排序之插入排序
    编写高质量代码 改善Python程序的91个建议——笔记(三)
    ImportHelper 导出帮助类
    使用Layer弹出一个页面
    MongoDB使用手册
    MVC4设置@Html.BeginForm的ID
    LayerManage
    Layer弹窗返回数据回调
  • 原文地址:https://www.cnblogs.com/mingjiatang/p/9542531.html
Copyright © 2011-2022 走看看