python的模拟登录原理_爬虫之模拟用户登录

爬虫经常会碰到的一个问题就是获取目标网页的内容需要用户登录,而一贯的做法就是模拟用户登录,获取cookie后再抓取网页内容。不过,今天让我们来另辟蹊径……

原理

如果我们没有太多的时间精力来模拟用户登录(那啥,产品经理说:这个需求很简单,怎么实现我不管,明天上线!),又或者用户登录步骤过于复杂(各种加密、验证问题),我们有什么方法可以快速略过这一步而不影响后续网页内容抓取呢?没错,直接复用浏览器的Cookie!

我们在浏览器中访问网页后正常登录,浏览器保存的cookie显然是保存在本地文件中,只要我们读取该文件的内容附加到http请求上,一切就大功告成啦。

举个栗子

我们以爬取 优酷自频道 排行榜为例,在Ubuntu下使用Google Chrome为辅助。

直接打开上面的链接,发现自动跳转到了用户登录页面,使用优酷账号正常登陆后,在chrome的开发者面板即可看到相应的cookie信息。

Chrome Cookie

默认情况下,Ubuntu的Chrome Cookie存放在 /home/user/.config/google-chrome/Profile/Cookies ,文件格式为 SQLite,表结构大致为:字段名称字段类型

creation_utcInteger primary key

host_keyText

nameText

valueText

pathText

expires_utcInteger

secureInteger

httponlyInteger

last_access_utcInteger

has_expiresInteger

persistentInteger

priorityInteger

encrypted_valueBlob

firstpartyonlyInteger

主要字段 host_key, name, value, path, encrypted_value. 我们简单看一下数据:

chrome cookie

Python

def get_cookie():

cookie_path = os.path.join(os.getenv("HOME"), ".config/google-chrome/Default/Cookies")

with sqlite3.connect(cookie_path) as conn:

cur = conn.cursor()

sql = "select host_key, name, value, path, encrypted_value from cookies where host_key = ?"

cur.execute(sql, (".youku.com",))

rows = cur.fetchall()

print "total cookies: ", len(rows)

for row in rows:

print row

1

2

3

4

5

6

7

8

9

10defget_cookie():

cookie_path=os.path.join(os.getenv("HOME"),".config/google-chrome/Default/Cookies")

withsqlite3.connect(cookie_path)asconn:

cur=conn.cursor()

sql="select host_key, name, value, path, encrypted_value from cookies where host_key = ?"

cur.execute(sql,(".youku.com",))

rows=cur.fetchall()

print"total cookies: ",len(rows)

forrowinrows:

printrow

结果发现value为空,chrome cookie进行加密保存在 encrypted_value 字段:

result

Default

total cookies: 7

(u'.youku.com', u'__ysuid', u'', u'/', )

(u'.youku.com', u'__yscnt', u'', u'/', )

(u'.youku.com', u'__ayvstp', u'', u'/', )

(u'.youku.com', u'juid', u'', u'/', )

(u'.youku.com', u'cna', u'', u'/', )

(u'.youku.com', u'l', u'', u'/', )

(u'.youku.com', u'isg', u'', u'/', )

1

2

3

4

5

6

7

8totalcookies:7

(u'.youku.com',u'__ysuid',u'',u'/',)

(u'.youku.com',u'__yscnt',u'',u'/',)

(u'.youku.com',u'__ayvstp',u'',u'/',)

(u'.youku.com',u'juid',u'',u'/',)

(u'.youku.com',u'cna',u'',u'/',)

(u'.youku.com',u'l',u'',u'/',)

(u'.youku.com',u'isg',u'',u'/',)

Cookie解密Some more details from the source: Password is: “peanuts” Salt is: “saltysalt” The number of KDF iterations is: 1 Algorithm: AES-128-CBC [Edit] Clarify that no. of iterations is for the Key Derivation Function

因此我们可以进行解密:

Default

from Crypto.Cipher import AES

from Crypto.Protocol.KDF import PBKDF2

def decrypt(encrypted_value):

encrypted_value = encrypted_value[3:]

salt = "saltysalt"

length = 16

my_pass = "peanuts"

iterations = 1

key = PBKDF2(my_pass, salt, length, iterations)

iv = " " * 16

cipher = AES.new(key, AES.MODE_CBC, IV=iv)

decrypted = cipher.decrypt(encrypted_value)

return decrypted

def clean(x):

return x[:-ord(x[-1])].decode('utf8')

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18fromCrypto.CipherimportAES

fromCrypto.Protocol.KDFimportPBKDF2

defdecrypt(encrypted_value):

encrypted_value=encrypted_value[3:]

salt="saltysalt"

length=16

my_pass="peanuts"

iterations=1

key=PBKDF2(my_pass,salt,length,iterations)

iv=" "*16

cipher=AES.new(key,AES.MODE_CBC,IV=iv)

decrypted=cipher.decrypt(encrypted_value)

returndecrypted

defclean(x):

returnx[:-ord(x[-1])].decode('utf8')

另外,在MacOS、Windows下Chrome cookie的加密方式稍有区别,具体可以参考 browsercookie源码。

Browsercookie

看了上面的实现过程,是不是觉得麻烦?OK,直接使用现成的第三方库 browsercookie,它已经把上面的cookie解密实现了:

chrome cookiejar

Python

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import requests

import browsercookie

def main():

cookiejar = browsercookie.chrome()

url = "http://www.youku.com/u/channelRanking?channel=0&rank=0&pn=1&ajaxget=1"

r = requests.get(url, cookies=cookiejar)

r.raise_for_status()

print r.text()

if __name__ == "__main__":

main()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17#!/usr/bin/env python

# -*- coding: utf-8 -*-

importrequests

importbrowsercookie

defmain():

cookiejar=browsercookie.chrome()

url="http://www.youku.com/u/channelRanking?channel=0&rank=0&pn=1&ajaxget=1"

r=requests.get(url,cookies=cookiejar)

r.raise_for_status()

printr.text()

if__name__=="__main__":

main()

另外,browsercookie也可以直接读取Firefox的Cookie,使用方法类似Chrome:

firefox cookiejar

Python

cookiejar = browsercookie.firefox()

1cookiejar=browsercookie.firefox()

搞完收工,今晚是不是可以早点下班啦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值