Python:黑板课爬虫闯关第三关

python学习网 2018-09-16 08:30:03

第三关开始才算是进入正题了。

输入网址 http://www.heibanke.com/lesson/crawler_ex02/,直接跳转到了 http://www.heibanke.com/accounts/login/?next=/lesson/crawler_ex02/,显示如下

看到这个一愣,怎么不是第三关呢?不管,也许是标题不一样吧。点个注册看了下,里面有个验证码,顿时以为是考验证码破解。

注册以后,跳转到不知道哪里去了,重新输入 http://www.heibanke.com/lesson/crawler_ex02/,一看,原来想错了。

原来这才是第三关,首先可以肯定的是,必须要先登录,并保持登录状态,否则是爬不过关的。

我用的是谷歌浏览器,打开开发者工具,随便输了个昵称和密码,追踪一下网络请求

这个 csrfmiddlewaretoken 又是个什么鬼,哪里来的?

用代码试下登录看。post 用户名密码之后,print 一下响应的 html,发现并不是我看到的第三关的内容,说明登录没有成功。看一下里面有一句话:You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties.

简单的说,就是为了防止CSRF攻击(其实就是黑板课设的障碍),需要一个cookie。那么就简单了,csrfmiddlewaretoken 想必就是那个 cookie 了。

追踪一下登录的网络请求,发现也有 csrfmiddlewaretoken,想必内外是一样的机制。

请求网址的时候,返回一个名为 csrftoken 的 cookie,这个 cookie 的值就是 post 的时候需要的 csrfmiddlewaretoken 参数。

这样思路就理清了,每次 post 用户名密码之前,先 get 请求一下,从服务器发给你的 cookie 中获取 csrftoken 的值作为 post 时的 csrfmiddlewaretoken 参数即可。

代码如下:

import re
import requests
import time


def main():
    url_login = 'http://www.heibanke.com/accounts/login/?next=/lesson/crawler_ex02/'
    url = 'http://www.heibanke.com/lesson/crawler_ex02/'
    session = requests.Session()
    # 获取cookie
    session.get(url_login)
    token = session.cookies['csrftoken']
    # 登录
    session.post(url_login, data={'csrfmiddlewaretoken': token, 'username': 'guliang21', 'password': '123qwe'})
    for psd in range(30):
        print(f'test password {psd}')
        session.get(url)
        token = session.cookies['csrftoken']
        r = session.post(url, data={'csrfmiddlewaretoken': token, 'username': 'aa', 'password': psd})
        html = r.text
        if '密码错误' not in html:
            m = re.search('(?<=\<h3\>).*?(?=\</h3\>)', html)
            print(m.group())
            m = re.search('(\<).*?href="([^"]*?)".*?(\>下一关\</a\>)', html)
            print(f'下一关 http://www.heibanke.com{m.group(2)}')
            return
        else:
            time.sleep(1)


if __name__ == '__main__':
    main()

 

阅读(2650) 评论(0)