Python 开发网络爬虫(四): 登陆

http://blog.jobbole.com/77878/ html

博客 – 伯乐在线正则表达式

首页最新文章在线课程业界开发 IT技术 设计 创业IT职场投稿更多 »浏览器

伯乐在线 > 首页 > 全部文章 > Python > 零基础自学用Python 3开发网络爬虫(四): 登陆服务器

零基础自学用Python 3开发网络爬虫(四): 登陆cookie


原文出处: Jecvay Notes (@Jecvay)   欢迎分享原创到伯乐头条网络

今天的工做颇有意思, 咱们用 Python 来登陆网站, 用Cookies记录登陆信息, 而后就能够抓取登陆以后才能看到的信息. 今天咱们拿知乎网来作示范. 为何是知乎? 这个很难解释, 可是确定的是知乎这么大这么成功的网站彻底不用我来帮他打广告. 知乎网的登陆比较简单, 传输的时候没有对用户名和密码加密, 却又不失表明性, 有一个必须从主页跳转登陆的过程.app


不得不说一下, Fiddler 这个软件是 Tpircsboy 告诉个人. 感谢他给我带来这么好玩的东西.ide


 


第一步: 使用 Fiddler 观察浏览器行为函数


在开着 Fiddler 的条件下运行浏览器, 输入知乎网的网址 http://www.zhihu.com 回车后到 Fiddler 中就能看到捕捉到的链接信息. 在左边选中一条 200 链接, 在右边打开 Inspactors 透视图, 上方是该条链接的请求报文信息, 下方是响应报文信息.post

其中 Raw 标签是显示报文的原文. 下方的响应报文颇有多是没有通过解压或者解码的, 这种状况他会在中间部位有一个小提示, 点击一下就能解码显示出原文了.




 


以上这个截图是在未登陆的时候进入 http://www.zhihu.com 获得的. 如今咱们来输入用户名和密码登录知乎网, 再看看浏览器和知乎服务器之间发生了什么.




 


点击登录后, 回到 Fiddler 里查看新出现的一个 200 连接. 咱们浏览器携带者个人账号密码给知乎服务器发送了一个 POST, 内容以下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

POST http://www.zhihu.com/login HTTP/1.1

Content-Type: application/x-www-form-urlencoded; charset=UTF-8

Accept: */*

X-Requested-With: XMLHttpRequest

Referer: http://www.zhihu.com/#signin

Accept-Language: en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/5.0 (Windows NT 6.4; WOW64; Trident/7.0; rv:11.0) like Gecko

Content-Length: 97

DNT: 1

Host: www.zhihu.com

Connection: Keep-Alive

Pragma: no-cache

Cookie: __utma=51854390.1539896551.1412320246.1412320246.1412320246.1; __utmb=51854390.6.10.1412320246; __utmc=51854390; __utmz=51854390.1412320246.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmv=51854390.000–|3=entry_date=20141003=1

 

_xsrf=4b41f6c7a9668187ccd8a610065b9718&email=此处涂黑%40gmail.com&password=此处不可见&rememberme=y

截图以下:




个人浏览器给 http://www.zhihu.com/login 这个网址(多了一个/login) 发送了一个POST, 内容都已经在上面列出来了, 有用户名, 有密码, 有一个”记住我”的 yes, 其中这个 WebForms 标签下 Fiddler 可以比较层次分明的列出来 POST 的内容. 因此咱们用 Python 也发送相同的内容就能登陆了. 可是这里出现了一个 Name 为 _xsrf 的项, 他的值是 4b41f6c7a9668187ccd8a610065b9718. 咱们要先获取这个值, 而后才能给他发.


浏览器是如何获取的呢, 咱们刚刚是先访问了 http://www.zhihu.com/ 这个网址, 就是首页, 而后登陆的时候他却给 http://www.zhihu.com/login 这个网址发信息. 因此用侦探通常的思惟去思考这个问题, 就会发现确定是首页把 _xsrf 生成发送给咱们, 而后咱们再把这个 _xsrf 发送给 /login 这个 url. 这样一下子事后咱们就要从第一个 GET 获得的响应报文里面去寻找 _xsrf


截图下方的方框说明, 咱们不只登陆成功了, 并且服务器还告诉咱们的浏览器如何保存它给出的 Cookies 信息. 因此咱们也要用 Python 把这些 Cookies 信息记录下来.


这样 Fiddler 的工做就基本结束了!


 


第二步: 解压缩


简单的写一个 GET 程序, 把知乎首页 GET 下来, 而后 decode() 一下解码, 结果报错. 仔细一看, 发现知乎网传给咱们的是通过 gzip 压缩以后的数据. 这样咱们就须要先对数据解压. Python 进行 gzip 解压很方便, 由于内置有库能够用. 代码片断以下:


1

2

3

4

5

6

7

8

9

import gzip

def ungzip(data):

    try:        

# 尝试解压

        print('正在解压.....')

        data = gzip.decompress(data)

        print('解压完毕!')

    except:

        print('未经压缩, 无需解压')

    return data

经过 opener.read() 读取回来的数据, 通过 ungzip 自动处理后, 再来一遍 decode() 就能够获得解码后的 str 了


 


第二步: 使用正则表达式获取沙漠之舟


_xsrf 这个键的值在茫茫无际的互联网沙漠之中指引咱们用正确的姿式来登陆知乎, 因此 _xsrf 可谓沙漠之舟. 若是没有 _xsrf, 咱们或许有用户名和密码也没法登陆知乎(我没试过, 不过咱们学校的教务系统确实如此) 如上文所说, 咱们在第一遍 GET 的时候能够从响应报文中的 HTML 代码里面获得这个沙漠之舟. 以下函数实现了这个功能, 返回的 str 就是 _xsrf 的值.


1

2

3

4

5

import re

def getXSRF(data):

    cer = re.compile('name=\"_xsrf\" value=\"(.*)\"', flags = 0)

    strlist = cer.findall(data)

    return strlist[0]

第三步: 发射 POST !!


集齐 _xsrf, id, password 三大法宝, 咱们能够发射 POST 了. 这个 POST 一旦发射过去, 咱们就登录上了服务器, 服务器就会发给咱们 Cookies. 原本处理 Cookies 是个麻烦的事情, 不过 Python 的 http.cookiejar 库给了咱们很方便的解决方案, 只要在建立 opener 的时候将一个 HTTPCookieProcessor 放进去, Cookies 的事情就不用咱们管了. 下面的代码体现了这一点.


1

2

3

4

5

6

7

8

9

10

11

12

13

import http.cookiejar

import urllib.request

def getOpener(head):

    

# deal with the Cookies

    cj = http.cookiejar.CookieJar()

    pro = urllib.request.HTTPCookieProcessor(cj)

    opener = urllib.request.build_opener(pro)

    header = []

    for key, value in head.items():

        elem = (key, value)

        header.append(elem)

    opener.addheaders = header

    return opener

getOpener 函数接收一个 head 参数, 这个参数是一个字典. 函数把字典转换成元组集合, 放进 opener. 这样咱们创建的这个 opener 就有两大功能:


自动处理使用 opener 过程当中遇到的 Cookies

自动在发出的 GET 或者 POST 请求中加上自定义的 Header


第四部: 正式运行


正式运行还差一点点, 咱们要把要 POST 的数据弄成 opener.open() 支持的格式. 因此还要 urllib.parse 库里的 urlencode() 函数. 这个函数能够把 字典 或者 元组集合 类型的数据转换成 & 链接的 str.


str 还不行, 还要经过 encode() 来编码, 才能看成 opener.open() 或者 urlopen() 的 POST 数据参数来使用. 代码以下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

url = 'http://www.zhihu.com/'

opener = getOpener(header)

op = opener.open(url)

data = op.read()

data = ungzip(data)     

# 解压

_xsrf = getXSRF(data.decode())

  

url += 'login'

id = '这里填你的知乎账号'

password = '这里填你的知乎密码'

postDict = {

        '_xsrf':_xsrf,

        'email': id,

        'password': password,

        'rememberme': 'y'

}

postData = urllib.parse.urlencode(postDict).encode()

op = opener.open(url, postData)

data = op.read()

data = ungzip(data)

  

print(data.decode())  

# 你能够根据你的喜欢来处理抓取回来的数据了!

代码运行后, 咱们发现本身关注的人的动态(显示在登录后的知乎首页的那些), 都被抓取回来了. 下一步作一个统计分析器, 或者自动推送器, 或者内容分级自动分类器, 均可以.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

import gzip

import re

import http.cookiejar

import urllib.request

import urllib.parse

  

def ungzip(data):

    try:        

# 尝试解压

        print('正在解压.....')

        data = gzip.decompress(data)

        print('解压完毕!')

    except:

        print('未经压缩, 无需解压')

    return data

  

def getXSRF(data):

    cer = re.compile('name=\"_xsrf\" value=\"(.*)\"', flags = 0)

    strlist = cer.findall(data)

    return strlist[0]

  

def getOpener(head):

    

# deal with the Cookies

    cj = http.cookiejar.CookieJar()

    pro = urllib.request.HTTPCookieProcessor(cj)

    opener = urllib.request.build_opener(pro)

    header = []

    for key, value in head.items():

        elem = (key, value)

        header.append(elem)

    opener.addheaders = header

    return opener

  

header = {

    'Connection': 'Keep-Alive',

    'Accept': 'text/html, application/xhtml+xml, */*',

    'Accept-Language': 'en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3',

    'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko',

    'Accept-Encoding': 'gzip, deflate',

    'Host': 'www.zhihu.com',

    'DNT': '1'

}

  

url = 'http://www.zhihu.com/'

opener = getOpener(header)

op = opener.open(url)

data = op.read()

data = ungzip(data)     

# 解压

_xsrf = getXSRF(data.decode())

  

url += 'login'

id = '这里填你的知乎账号'

password = '这里填你的知乎密码'

postDict = {

        '_xsrf':_xsrf,

        'email': id,

        'password': password,

        'rememberme': 'y'

}

postData = urllib.parse.urlencode(postDict).encode()

op = opener.open(url, postData)

data = op.read()

data = ungzip(data)

  

print(data.decode())

相关文章
相关标签/搜索