您的位置:澳门新葡8455最新网站 > 编程教学 > Python爬取知乎与我所理解的爬虫与反爬虫,pyth

Python爬取知乎与我所理解的爬虫与反爬虫,pyth

发布时间:2019-11-04 10:57编辑:编程教学浏览(163)

    多年来在练习写爬虫的时候,恰巧同学的女对象有必要,大约是爬取知网内的几千个大旨的数额,每叁个大旨的条数记录有几条的到几千条的不如,总来的来讲也总算个上万数额级的爬虫了,解析了下知网,发掘使用专门的学问检索,能够成功自己的靶子,然后经过chrome的developer tools大致解析了下了央浼数据包,发掘知网的询问是分成两步的,第一步是叁个总的央求(查询的原则基本上都在第一步里面了卡塔 尔(英语:State of Qatar),会回来多少个串

    博客园已经济体制校勘成了爬虫的篮球场,本文利用Python中的requests库,模拟登录天涯论坛,获取cookie,保存到地面,然后那些cookie作为登入的凭证,登录和讯的主页面,爬取和讯主页面上的难点和对应难题回答的摘要。

    有关果壳网验证码登入的难题,用到了Python上二个主要的图纸管理库PIL,倘诺不行,就把图片存到本地,手动输入。

    图片 1

    爬取果壳网的入眼的片段:模拟登入

    因而对博客园登录是的抓包,能够开采登入微博,必要post多个参数,三个是账号,三个是密码,叁个是xrsf。
    其豆蔻梢头xrsf隐敝在表单里面,每便登录的时候,应该是服务器随机发生一个字符串。全部,要效仿登录的时候,必须求获得xrsf。

    用chrome (恐怕火狐 httpfox 抓包剖判卡塔尔国的结果:

    image.png

    故此,必必要获得xsrf的数值,注意那是一个动态变化的参数,每一回都不相像。

    image.png

    注意findall和find_all函数的界别。

    得到xsrf,上边就足以依样葫芦登录了。
    应用requests库的session对象,建构二个对话的好处是,能够把同一个顾客的不等哀告联系起来,直到会话甘休都会活动管理cookies。

    image.png

    注意:cookies 是当前目录的一个文件,那一个文件保留了知乎的cookie,假若是率先个登入,那么自然是从未那一个文件的,不能够通过cookie文件来登入。必必要输入密码。

    def login(secret, account):
        # 通过输入的用户名判断是否是手机号
        if re.match(r"^1d{10}$", account):
            print("手机号登录 n")
            post_url = 'https://www.zhihu.com/login/phone_num'
            postdata = {
                '_xsrf': get_xsrf(),
                'password': secret,
                'remember_me': 'true',
                'phone_num': account,
            }
        else:
            if "@" in account:
                print("邮箱登录 n")
            else:
                print("你的账号输入有问题,请重新登录")
                return 0
            post_url = 'https://www.zhihu.com/login/email'
            postdata = {
                '_xsrf': get_xsrf(),
                'password': secret,
                'remember_me': 'true',
                'email': account,
            }
        try:
            # 不需要验证码直接登录成功
            login_page = session.post(post_url, data=postdata, headers=headers)
            login_code = login_page.text
            print(login_page.status_code)
            print(login_code)
        except:
            # 需要输入验证码后才能登录成功
            postdata["captcha"] = get_captcha()
            login_page = session.post(post_url, data=postdata, headers=headers)
            login_code = eval(login_page.text)
            print(login_code['msg'])
        session.cookies.save()
    try:
        input = raw_input
    except:
        pass
    

    那是登录的函数,通过login函数来登入,post 本身的账号,密码和xrsf 到和讯登录认证的页面上去,然后拿走cookie,将cookie保存到当前目录下的文件之中。下一次登入的时候,直接读取这几个cookie文件。

    #LWP-Cookies-2.0
    Set-Cookie3: cap_id=""YWJkNTkxYzhiMGYwNDU2OGI4NDUxN2FlNzBmY2NlMTY=|1487052577|4aacd7a27b11a852e637262bb251d79c6cf4c8dc""; path="/"; domain=".zhihu.com"; path_spec; expires="2017-03-16 06:09:37Z"; version=0
    Set-Cookie3: l_cap_id=""OGFmYTk3ZDA3YmJmNDQ4YThiNjFlZjU3NzQ5NjZjMTA=|1487052577|0f66a8f8d485bc85e500a121587780c7c8766faf""; path="/"; domain=".zhihu.com"; path_spec; expires="2017-03-16 06:09:37Z"; version=0
    Set-Cookie3: login=""NmYxMmU0NWJmN2JlNDY2NGFhYzZiYWIxMzE5ZTZiMzU=|1487052597|a57652ef6e0bbbc9c4df0a8a0a59b559d4e20456""; path="/"; domain=".zhihu.com"; path_spec; expires="2017-03-16 06:09:57Z"; version=0
    Set-Cookie3: q_c1="ee29042649aa4f87969ed193acb6cb83|1487052577000|1487052577000"; path="/"; domain=".zhihu.com"; path_spec; expires="2020-02-14 06:09:37Z"; version=0
    Set-Cookie3: z_c0=""QUFCQTFCOGdBQUFYQUFBQVlRSlZUVFVzeWxoZzlNbTYtNkt0Qk1NV0JLUHZBV0N6NlNNQmZ3PT0=|1487052597|dcf272463c56dd6578d89e3ba543d46b44a22f68""; path="/"; domain=".zhihu.com"; path_spec; expires="2017-03-16 06:09:57Z"; httponly=None; version=0
    

    这是cookie文件的内容

    以下是源码:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import requests
    try:
        import cookielib
    except:
        import http.cookiejar as cookielib
    import re
    import time
    import os.path
    try:
        from PIL import Image
    except:
        pass
    
    from bs4 import BeautifulSoup
    
    
    # 构造 Request headers
    agent = 'Mozilla/5.0 (Windows NT 5.1; rv:33.0) Gecko/20100101 Firefox/33.0'
    headers = {
        "Host": "www.zhihu.com",
        "Referer": "https://www.zhihu.com/",
        'User-Agent': agent
    }
    
    # 使用登录cookie信息
    session = requests.session()
    session.cookies = cookielib.LWPCookieJar(filename='cookies')
    try:
        session.cookies.load(ignore_discard=True)
    except:
        print("Cookie 未能加载")
    
    
    
    def get_xsrf():
        '''_xsrf 是一个动态变化的参数'''
        index_url = 'https://www.zhihu.com'
        # 获取登录时需要用到的_xsrf
        index_page = session.get(index_url, headers=headers)
        html = index_page.text
        pattern = r'name="_xsrf" value="(.*?)"'
        # 这里的_xsrf 返回的是一个list
        _xsrf = re.findall(pattern, html)
        return _xsrf[0]
    
    
    
    
    
    # 获取验证码
    def get_captcha():
        t = str(int(time.time() * 1000))
        captcha_url = 'https://www.zhihu.com/captcha.gif?r=' + t + "&type=login"
        r = session.get(captcha_url, headers=headers)
        with open('captcha.jpg', 'wb') as f:
            f.write(r.content)
            f.close()
        # 用pillow 的 Image 显示验证码
        # 如果没有安装 pillow 到源代码所在的目录去找到验证码然后手动输入
        try:
            im = Image.open('captcha.jpg')
            im.show()
            im.close()
        except:
            print(u'请到 %s 目录找到captcha.jpg 手动输入' % os.path.abspath('captcha.jpg'))
        captcha = input("please input the captchan>")
        return captcha
    
    
    
    
    
    def isLogin():
        # 通过查看用户个人信息来判断是否已经登录
        url = "https://www.zhihu.com/settings/profile"
        login_code = session.get(url, headers=headers, allow_redirects=False).status_code
        if login_code == 200:
            return True
        else:
            return False
    
    
    def login(secret, account):
        # 通过输入的用户名判断是否是手机号
        if re.match(r"^1d{10}$", account):
            print("手机号登录 n")
            post_url = 'https://www.zhihu.com/login/phone_num'
            postdata = {
                '_xsrf': get_xsrf(),
                'password': secret,
                'remember_me': 'true',
                'phone_num': account,
            }
        else:
            if "@" in account:
                print("邮箱登录 n")
            else:
                print("你的账号输入有问题,请重新登录")
                return 0
            post_url = 'https://www.zhihu.com/login/email'
            postdata = {
                '_xsrf': get_xsrf(),
                'password': secret,
                'remember_me': 'true',
                'email': account,
            }
        try:
            # 不需要验证码直接登录成功
            login_page = session.post(post_url, data=postdata, headers=headers)
            login_code = login_page.text
            print(login_page.status_code)
            print(login_code)
        except:
            # 需要输入验证码后才能登录成功
            postdata["captcha"] = get_captcha()
            login_page = session.post(post_url, data=postdata, headers=headers)
            login_code = eval(login_page.text)
            print(login_code['msg'])
        session.cookies.save()
    try:
        input = raw_input
    except:
        pass
    
    
    
    ## 將main的問題列表輸出在shell上面
    def  getPageQuestion(url2):  
      mainpage = session.get(url2, headers=headers)
      soup=BeautifulSoup(mainpage.text,'html.parser')
      tags=soup.find_all("a",class_="question_link")
      #print tags
    
      for tag in tags:
        print tag.string
    
    # 將main頁面上面的問題的回答的摘要輸出在shell上面
    def getPageAnswerAbstract(url2):
        mainpage=session.get(url2,headers=headers)
        soup=BeautifulSoup(mainpage.text,'html.parser')
        tags=soup.find_all('div',class_='zh-summary summary clearfix')
    
        for tag in tags:
           # print tag
            print tag.get_text()
            print '詳細內容的鏈接 : ',tag.find('a').get('href')
    
    
    def getPageALL(url2):
        #mainpage=session.get(url2,headers=headers)
        #soup=BeautifulSoup(mainpage.text,'html.parser')
        #tags=soup.find_all('div',class_='feed-item-inner')
        #print "def getpageall "
        mainpage=session.get(url2,headers=headers)
        soup=BeautifulSoup(mainpage.text,'html.parser')
        tags=soup.find_all('div',class_='feed-content')
        for tag in tags:
            #print tag
            print tag.find('a',class_='question_link').get_text()
            # 這裏有一點問題 bs 還是用的不是太熟練
            #print tag.find('a',class_='zh-summary summary clearfix').get_text()
            #print tag.find('div',class_='zh-summary summary clearfix').get_text()
    
    
    if __name__ == '__main__':
        if isLogin():
            print('您已经登录')
            url2='https://www.zhihu.com'
            # getPageQuestion(url2)
            #getPageAnswerAbstract(url2)
            getPageALL(url2)
        else:
            account = input('请输入你的用户名n>  ')
            secret = input("请输入你的密码n>  ")
            login(secret, account)
    

    运行结果:

    image.png

    接下来本领做第二步的数码央浼(下方的截图对应网页上的不等区域的倡议报文头和重临数据卡塔 尔(英语:State of Qatar)

    git链接:

    https://github.com/zhaozhengcoder/Spider/tree/master/spider_zhihu

    图片 2

    PPS:小编所领悟的爬虫与反爬虫攻略

    反爬虫最大旨的计划:

    1. 自己商酌浏览器http央求里面包车型客车user-agent字段
    2. 自己商量http央求的referer(即当前的那一个页面是从哪个页面跳转过来的卡塔 尔(英语:State of Qatar)

    爬虫攻略:
    那多少个都以在http合同的报文段的检讨,相近爬虫端能够极低价的装置这么些字段的值,来招摇撞骗服务器。

    反爬虫进级计谋:
    1.像今日头条形似,在签到的表单里面归入三个掩盖字段,里面会有叁个随意数,每便都分裂等,那样除非你的爬虫脚本能够解析这些自由数,不然后一次爬的时候就非常了。
    2.笔录拜访的ip,总括访谈次数,倘若次数太高,能够以为那几个ip不正常。

    爬虫进级战术:
    1.像这篇小说提到的,爬虫也能够先深入剖判一下隐敝字段的值,然后再拓宽效仿登陆。
    2.爬虫能够应用ip代理池的法门,来防止被发觉。同期,也得以爬一会安歇一会的措施来下滑效用。此外,服务器依照ip访问次数来扩充反爬,再ipv6未有全面推广的时期,那几个计谋会相当轻便引致危机。(这几个是本身个人的知道卡塔尔。

    反爬虫进升级计谋:
    1.数量投毒,服务器在大团结的页面上放置非常多潜藏的url,这一个url存在于html文件文件之中,可是通过css大概js使她们不会被展现在用户旁观的页面上边。(确认保证客商点击不到卡塔 尔(阿拉伯语:قطر‎。那么,爬虫在爬取网页的时候,很用大概取访问那个url,服务器能够百分百的认为这是爬虫干的,然后能够重返给她有个别乖谬的多寡,只怕是不容响应。

    爬虫进进级战略:
    1.生龙活虎一网址尽管需求反爬虫,然而不可见把百度,谷歌(Google卡塔 尔(英语:State of Qatar)那般的追寻引擎的爬虫给干了(干了的话,你的网站在百度都在说搜不到!卡塔尔国。这样爬虫应该就能够以假乱真是百度的爬虫去爬。(可是ip可能可能被搜查缴获,因为你的ip实际不是百度的ip卡塔尔国

    反爬虫进进进级攻略:
    给个验证码,令你输入现在手艺登入,登陆之后,工夫访谈。

    爬虫进进进级战略:
    图像识别,机器学习,识别验证码。可是这一个应该相比难,可能说花费相比较高。

    参照他事他说加以考察资料:
    廖雪峰的python教程
    静觅的python教程
    requests库官方文档
    segmentfault上边有壹位的有关搜狐爬虫的博客,找不到链接了

                                                                           图生机勃勃.询问记录央浼报文头

    图片 3

                                                                            图二. 对应不相同年份的笔录条数重临结果

    关于何以要分成两步,每贰个区域对应多个不风度翩翩的伸手,这么些都以网址本人的统筹,我也没做过web开垦,这么做有怎样优点小编确实不知道/擦汗,小编的首要就是模拟它在网页上的号令,达成批量化的数据拿到。

     

    下一场,差比超级少就摸清楚了那二个数量获得的进度,小编的思绪是先成功三个数码级的数量得到,相当于爬取一条,然后再去扩张,加线程,加ip代理,加user_agent等等。

    在这里个阶段,首要的思路正是大半要和在网页上的会见保持后生可畏致,保证自个儿拼的url和在网页上访谈的时候是同等的,当然是在保管能访谈的前提下,能略去的就略去。

    深入分析它原先的乞请url的时候,使用url转码工具得以将转码现在的url还原,越来越直白地解析。

    接下来提多少个细节呢,知网的倡议url上,有一点点数量段一同初是不通晓它的意思的,可是本人去拼接访问的时候发掘,缺了网址就能够报错,当时就足以多尝试多少个分裂的拜谒,去拿它的倡议heads,然后互绝比较,就能意识有些字段是长久不改变的,这种就可以间接照搬,有的吧,是浮动的,这种就必要精心去深入分析到底是怎样数据,有何含义,知网的就回顾一个纳秒数,那一个自个儿一开首就没懂具体意思,后来深入分析了下认为像时光,然后去取了下当前的飞秒时间,生机勃勃比较开掘大约是大半,就这段时间的飞秒时间拼在了url串上面。

    def getMilliTim():
        t = time.time()
        nowTime = t*1000
        return int(nowTime)
    

    假定您须求一个绝妙的读书调换条件,那么你能够思忖Python学习沟通群:548377875; 要是您须要风度翩翩份系统的就学资料,那么您能够思量Python学习沟通群:548377875。

    一言以蔽之,正是对此有个别懂web的爬虫小白,最好正是还原网址原来的央浼,那样基本上乞求数据就不会有太大主题素材了。

    在成就了数额级为黄金年代的等第后,就最早筹划大规模地获取数据了,那时候将要思谋功用以致堤防网址踢人了。

    在饱受了各样socket 10054 10061等错误,通过百度种种手艺,加上了ip代理等局地办法,最终自身要么到位本次职务,当然最后依旧增进了文本读取,职责队列等模块,大约正是多少个线程专责输出文件,别的八个线程去职务池里面取任务爬数据,详细略过,见代码。有疏漏之处,还请斧正。

    本文由澳门新葡8455最新网站发布于编程教学,转载请注明出处:Python爬取知乎与我所理解的爬虫与反爬虫,pyth

    关键词: