资讯专栏INFORMATION COLUMN

scrapy模拟登陆知乎--抓取热点话题

leanxi / 796人阅读

摘要:在抓取数据之前,请在浏览器中登录过知乎,这样才使得是有效的。所谓的模拟登陆,只是在中尽量的模拟在浏览器中的交互过程,使服务端无感抓包过程。若是帮你解决了问题,或者给了你启发,不要吝啬给加一星。

折腾了将近两天,中间数次想要放弃,还好硬着头皮搞下去了,在此分享出来,希望有同等需求的各位能少走一些弯路。
源码放在了github上, 欢迎前往查看。
若是帮你解决了问题,或者给了你启发,不要吝啬给加一星。

工具准备

在开始之前,请确保 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
模拟登陆

过程如下:

进入登录页,获取 HeaderCookie 信息,
完善的 Header 信息能尽量伪装爬虫, 有效 Cookie 信息能迷惑知乎服务端,使其认为当前登录非首次登录,若无有效 Cookie 会遭遇验证码。 在抓取数据之前,请在浏览器中登录过知乎,这样才使得 Cookie 是有效的。

HeaderCookie 整理如下:

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中尽量的模拟在浏览器中的交互过程,使服务端无感抓包过程。 请求中附加有效的 CookiesHeaders 头信息,可有效的迷惑服务端, 同时在交互的过程中,获取后续请求必要信息和认证信息,使得整个流程能不断先前。

若是你遇到什么问题,尽量提出来,欢迎一起来讨论解决。
源码放在了github上, 欢迎前往查看。
若是帮你解决了问题,或者给了你启发,不要吝啬给加一星。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/40789.html

相关文章

  • 首次公开,整理12年积累的博客收藏夹,零距离展示《收藏夹吃灰》系列博客

    摘要:时间永远都过得那么快,一晃从年注册,到现在已经过去了年那些被我藏在收藏夹吃灰的文章,已经太多了,是时候把他们整理一下了。那是因为收藏夹太乱,橡皮擦给设置私密了,不收拾不好看呀。 ...

    Harriet666 评论0 收藏0
  • Python入门网络爬虫之精华版

    摘要:学习网络爬虫主要分个大的版块抓取,分析,存储另外,比较常用的爬虫框架,这里最后也详细介绍一下。网络爬虫要做的,简单来说,就是实现浏览器的功能。 Python学习网络爬虫主要分3个大的版块:抓取,分析,存储 另外,比较常用的爬虫框架Scrapy,这里最后也详细介绍一下。 首先列举一下本人总结的相关文章,这些覆盖了入门网络爬虫需要的基本概念和技巧:宁哥的小站-网络爬虫,当我们在浏览器中输入...

    Bmob 评论0 收藏0
  • Scrapy 抓取知乎的问题

    摘要:从如何评价的话题下开始抓取问题,然后开始爬相关问题再循环对于每个问题抓取标题,关注人数,回答数等数据设置用户名和密码设置获取值获得验证码的地址准备下载验证码获取请求下载验证码打开验证码输入验证码请输入验证码输入账号和 从如何评价X的话题下开始抓取问题,然后开始爬相关问题再循环 对于每个问题抓取 标题,关注人数,回答数等数据 zhihuTopicSpider.py # -*- cod...

    xiao7cn 评论0 收藏0
  • 22、Python快速开发分布式搜索引擎Scrapy精讲—scrapy模拟登陆知乎倒立文字验证码识

    【百度云搜索,搜各种资料:http://www.bdyss.cn】 【搜网盘,搜各种资料:http://www.swpan.cn】 第一步。首先下载,大神者也的倒立文字验证码识别程序 下载地址:https://github.com/muchrooms/... 注意:此程序依赖以下模块包   Keras==2.0.1  Pillow==3.4.2  jupyter==1.0.0  matplotli...

    array_huang 评论0 收藏0
  • 23个Python爬虫开源项目代码,包含微信、淘宝、豆瓣、知乎、微博等

    摘要:今天为大家整理了个爬虫项目。地址新浪微博爬虫主要爬取新浪微博用户的个人信息微博信息粉丝和关注。代码获取新浪微博进行登录,可通过多账号登录来防止新浪的反扒。涵盖链家爬虫一文的全部代码,包括链家模拟登录代码。支持微博知乎豆瓣。 showImg(https://segmentfault.com/img/remote/1460000018452185?w=1000&h=667); 今天为大家整...

    jlanglang 评论0 收藏0

发表评论

0条评论

leanxi

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<