zoukankan      html  css  js  c++  java
  • scrapy模拟登陆知乎--抓取热点话题

    工具准备

    在开始之前,请确保 scrpay 正确安装,手头有一款简洁而强大的浏览器, 若是你有使用 postman 那就更好了。

    scrapy genspider zhihu

    使用以上命令生成知乎爬虫,代码如下:

    # -*- coding: utf-8 -*-
    import scrapy
    
    
    class ZhihuSpider(scrapy.Spider):
        name = 'zhihu'
        allowed_domains = ['www.zhihu.com']
        start_urls = ['http://www.zhihu.com/']
    
        def parse(self, response):
            pass

    有一点切记,不要忘了启用 Cookies切记切记 :

    # Disable cookies (enabled by default)
    COOKIES_ENABLED = True

    模拟登陆

    过程如下:

    • 进入登录页,获取 Header 和 Cookie 信息,
      完善的 Header 信息能尽量伪装爬虫, 有效 Cookie 信息能迷惑知乎服务端,使其认为当前登录非首次登录,若无有效 Cookie 会遭遇验证码。 在抓取数据之前,请在浏览器中登录过知乎,这样才使得 Cookie 是有效的。
    • 欢迎加入我的QQ群`923414804`与我一起学习,群里有我学习过程中整理的大量学习资料。加群即可免费获取

    Header 和 Cookie 整理如下:

    headers = {
        'Host':
        'www.zhihu.com',
        'Connection':
        'keep-alive',
        'Origin':
        'https://www.zhihu.com',
        'User-Agent':
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36',
        'Content-Type':
        'application/x-www-form-urlencoded; charset=UTF-8',
        'Accept':
        '*/*',
        'X-Requested-With':
        'XMLHttpRequest',
        'DNT':
        1,
        'Referer':
        'https://www.zhihu.com/',
        'Accept-Encoding':
        'gzip, deflate, br',
        'Accept-Language':
        'zh-CN,zh;q=0.8,en;q=0.6',
    }
    
    cookies = {
        'd_c0':
        '"AHCAtu1iqAmPTped76X1ZdN0X_qAwhjdLUU=|1458699045"',
        '__utma':
        '51854390.1407411155.1458699046.1458699046.1458699046.1',
        '__utmv':
        '51854390.000--|3=entry_date=20160322=1',
        '_zap':
        '850897bb-cba4-4d0b-8653-fd65e7578ac2',
        'q_c1':
        'b7918ff9a5514d2981c30050c8c732e1|1502937247000|1491446589000',
        'aliyungf_tc':
        'AQAAAHVgviiNyQsAOhSntJ5J/coWYtad',
        '_xsrf':
        'b12fdca8-cb35-407a-bc4c-6b05feff37cb',
        'l_cap_id':
        '"MDk0MzRjYjM4NjAwNDU0MzhlYWNlODQ3MGQzZWM0YWU=|1503382513|9af99534aa22d5db92c7f58b45f3f3c772675fed"',
        'r_cap_id':
        '"M2RlNDZjN2RkNTBmNGFmNDk2ZjY4NjIzY2FmNTE4NDg=|1503382513|13370a99ee367273b71d877de17f05b2986ce0ef"',
        'cap_id':
        '"NmZjODUxZjQ0NzgxNGEzNmJiOTJhOTlkMTVjNWIxMDQ=|1503382513|dba2e9c6af7f950547474f827ef440d7a2950163"',
    }
    • 在浏览器中,模拟登陆,抓取登陆请求信息。 

    从图中可以看到 _xsrf 参数, 这个参数与登陆验证信息无关,但很明显是由登陆页面携带的信息。 Google了下 xsrf 的含义, 用于防范 跨站请求伪造 。 


    • 整理以上,代码如下:

      loginUrl = 'https://www.zhihu.com/#signin'
      siginUrl = 'https://www.zhihu.com/login/email'
      
      
      def start_requests(self):
          return [
              scrapy.http.FormRequest(
                  self.loginUrl,
                  headers=self.headers,
                  cookies=self.cookies,
                  meta={'cookiejar': 1},
                  callback=self.post_login)
          ]
      
      
      def post_login(self, response):
          xsrf = response.css(
              'div.view-signin > form > input[name=_xsrf]::attr(value)'
          ).extract_first()
          self.headers['X-Xsrftoken'] = xsrf
      
          return [
              scrapy.http.FormRequest(
                  self.siginUrl,
                  method='POST',
                  headers=self.headers,
                  meta={'cookiejar': response.meta['cookiejar']},
                  formdata={
                      '_xsrf': xsrf,
                      'captcha_type': 'cn',
                      'email': 'xxxxxx@163.com',
                      'password': 'xxxxxx',
                  },
                  callback=self.after_login)
          ]

    设置Bearer Token

    经过上述步骤登陆成功了,有点小激动,有没有! 但苦难到此还远没有结束,这个时候尝试抓取最近热门话题,直接返回 code:401 ,未授权的访问。 授权信息未设置,导致了此类错误,莫非遗漏了什么,看来只能在浏览器中追踪请求参数来侦测问题。 在浏览器的请求中,包含了Bearer Token, 而我在scrapy中模拟的请求中未包含此信息, 所以我被服务器认定为未授权的。 通过观察发现 Bearer Token 的关键部分,就是 Cookies 中的 z_c0 包含的信息。


    z_c0 包含的信息,是在登陆完成时种下的,所以从登陆完成返回的登陆信息里,获取要设置的 Cookie 信息, 然后拼接出 Bearer Token,最后设置到 Header 中。

    代码整理如下:

    def after_login(self, response):
        jdict = json.loads(response.body)
        print('after_login', jdict)
        if jdict['r'] == 0:
            z_c0 = response.headers.getlist('Set-Cookie')[2].split(';')[0].split(
                '=')[1]
            self.headers['authorization'] = 'Bearer ' + z_c0
            return scrapy.http.FormRequest(
                url=self.feedUrl,
                method='GET',
                meta={'cookiejar': response.meta['cookiejar']},
                headers=self.headers,
                formdata={
                    'action_feed': 'True',
                    'limit': '10',
                    'action': 'down',
                    'after_id': str(self.curFeedId),
                    'desktop': 'true'
                },
                callback=self.parse)
        else:
            print(jdict['error'])

    获取数据

    上述步骤后,数据获取就水到渠成了,为了检测成功与否, 把返回信息写到文件中,而且只获取前五十个,代码如下:

    feedUrl = 'https://www.zhihu.com/api/v3/feed/topstory'
    nextFeedUrl = ''
    curFeedId = 0
    
    
    def parse(self, response):
        with open('zhihu.json', 'a') as fd:
            fd.write(response.body)
        jdict = json.loads(response.body)
        jdatas = jdict['data']
        for entry in jdatas:
            entry['pid'] = entry['id']
            yield entry
    
        jpaging = jdict['paging']
        self.curFeedId += len(jdatas)
        if jpaging['is_end'] == False and self.curFeedId < 50:
            self.nextFeedUrl = jpaging['next']
            yield self.next_request(response)
    
    
    def next_request(self, response):
        return scrapy.http.FormRequest(
            url=self.nextFeedUrl,
            method='GET',
            meta={'cookiejar': response.meta['cookiejar']},
            headers=self.headers,
            callback=self.parse)

    最终获取的数据如下图所示:

    写在最后

    知乎的数据,只有登录完成之后,才可有效的获取,所以模拟登陆是无法忽略不管的。 所谓的模拟登陆,只是在scrapy中尽量的模拟在浏览器中的交互过程,使服务端无感抓包过程。 请求中附加有效的 Cookies 和 Headers 头信息,可有效的迷惑服务端, 同时在交互的过程中,获取后续请求必要信息和认证信息,使得整个流程能不断先前。

  • 相关阅读:
    Bolero and Data Mining
    2007年3月15日 网站论坛出现以下错误/forum/inc/Dv_ClsMain.asp,行 1344
    A Probabilistic Model for Retrospective News Event
    信息抽取的资料文档
    Textual Data Mining and WEBSOM
    DockPanel Suite更新到2.6了 武胜
    Use Custom Events from your WCF ServiceHost http://www.codeproject.com/Tips/150702/UseCustomEventsfromyourWCFServiceHost 武胜
    Unable to convert MySQL date/time value to System.DateTime 解决方案 转 武胜
    XML 转义字符 武胜
    Using Nini .NET Configuration Library 武胜
  • 原文地址:https://www.cnblogs.com/paisenpython/p/10314012.html
Copyright © 2011-2022 走看看