★我要吧★

 找回密码
 注册[Register]
搜索
qq空间相册密码查看为什么登陆后需要激活无法注册?

[分享] QQ空间爬取教程

[复制链接]
发表于 2024-5-15 02:00:52 | 显示全部楼层 |阅读模式
selenium模拟登录8 d8 @$ P% |: L& c
QQ空间的反爬做的相对较好,而且由于好友权限的原因,我们要先登录后再进行说说等信息的获取7 w$ ?8 u" P# [/ o- y# b, m. X

8 D( r9 O; D: X5 L) p; K- J6 Yselenium是获取登录cookies的一大利器,非常方便7 d- Z% `" v- n) q/ m6 F
9 T& f2 V$ o( f9 C9 b1 S% R* v

6 B. R* j0 k5 E6 m+ X& n
7 i% o* K7 A* V, u4 T! B在空间的登陆界面可以观察到,登录的窗口与背景窗口是分开的,所以我们需要先切换框架
8 |! _& O1 n* E4 j* u' A
4 x) H) D7 C9 q: b2 y切换窗口后定位到账号密码登录元素的位置后点击: g& V$ |- Y7 j5 P6 e6 F( u
& j# J1 @5 S: f+ A, a: _
, n) L5 I! H' C1 C7 s; w  j' ^$ B
1 T4 ?6 ]/ e3 b& @  L
使用send_keys函数把账号和密码写入对应位置后定位登录元素后点击,这里使用自带的get_cookies函数获取到cookies,但是这个cookies需要过滤一下,具体操作看以下代码
9 ^  U+ H% v* Z( g. h
5 a: I! z( J; N$ x4 L% F代码为类的部分节选,完整代码在最后,未声明的变量皆为类的成员变量
: V6 [5 m5 H, s8 z' I
4 N' |5 f6 C; E$ W( P  a  b, Dde login_func(self,z):
* C' i$ i4 p( D browser = webdriver.Chrome()6 O5 D: _) T, O8 A
browser.maximize_window()
) U' T- y9 k7 j4 w4 `* ]( g. y browser.get(self.login_url)
, G( y( A: J' Z* [; h time.sleep(1.2)
' H7 W/ k  }' M' V! a browser.switch_to.frame('login_frame')
, Z5 S6 r' @& I5 e/ p browser.find_element_by_id('switcher_plogin').click()
9 y# |* ]$ S) D: `( m9 M  {  K, g time.sleep(1)
9 [" N) d' N2 }% ]4 ~/ L browser.find_element_by_id('u').send_keys(self.number)
5 J# O: `, k1 e& `  y browser.find_element_by_id('p').send_keys(self.password)
5 k& B+ y3 ~# J3 J) ` time.sleep(1)
$ n7 F/ m0 [$ i. r' |4 @ browser.find_element_by_id('login_button').click()( y4 k2 I; {1 ]6 u
time.sleep(1)
/ i. m6 q  ~1 ]8 r9 z! L( \ cookies_list = browser.get_cookies()  g$ b  ^' N' E' ~# J4 ]

0 f3 z& ?2 b, y' C* g' |' J for cookie in cookies_list:
& J- J$ ~  e% U! _( h if 'name' in cookie and 'value' in cookie:$ d3 T! \- ^8 v* i& }4 n
self.cookies[cookie['name']] = cookie['value']6 V" a% J! B9 |5 x
# print(self.cookies)
- s% A3 n  F' B# B6 m7 H" {* p: a with open('cookie_dict_{}.txt'.format(z),'w') as f: # 这里是为了一次性多刷几次cookies建立一个cookies池,便于加快爬虫速度,后面再提
2 Q: f) T# j& o$ E json.dump(self.cookies,f)
9 @9 X# }# ]1 A# browser.close()
5 f1 ^' q5 a$ i: |' i. x0 y" D" I5 n* ]; l# {
1
3 m! |: U, i8 E$ B2 U4 O: q$ M2
: L+ F. _* @0 z1 @' g- `4 C' N4 v2 P3: B7 m! n3 ^6 a/ d
4. g& }4 @' O: G% T% O
51 C4 i8 l- }) h' i2 Y
6
% k; ~% n0 L; A7
4 l; P! R% D  e! k: h8# I1 S  }/ ]1 L$ H& B
9( g( ]: i$ ]) Q1 X; @/ K
10
' @6 N/ }) H* w11
6 H; ^( n( Y5 z1 N% g, G0 l12$ {1 K; K# ?5 ?7 {
13
/ W9 g# j6 O; g5 D. S% P! R5 e2 ?; x
4 |- C. V; \( k- h! j; w$ w14 157 T+ |3 }/ a$ n0 o' i7 U
% Z# m4 Z5 k: D( b
16 17
7 ]' Y  [0 l  i; _18
+ V7 ~* r" V8 Y4 I6 F9 r& C$ Z19
; W! Y! |3 G2 n+ L20
& \& k1 k& q) [8 p, \) @21" S5 b' D5 S- y& v+ }
222 ?6 U9 K( `0 J. ~  K
说说内容获取
+ i2 W; O; W/ m在打开开发者工具后,在众多XHR对象中发现emotion_cgi......里面的msglist即是说说的内容
7 {. \/ i9 A, p
8 w: f# q: C6 Z2 I& C& P: {1 F. b
! G: ^0 m: @1 r% `
0 G& h: E* a0 _% B* Y! }) T2 ?$ |) Q5 k1 k- I  b' j

8 W' |  J" q) G+ P' ^这里的msglist是个列表,里面有0-20条不等的说说,可能跟空间发的说说的形式问题相关,至多不超过20条0 i/ x& N1 {, g1 c$ x3 K4 o% D# |
; W0 Q7 v) J" ^1 g
稍微猜测一下这里的参数的含义,一眼明了的我就不说了,我不清楚的也没有肆意揣度: h" p) c# w9 |; \  C( [
! U! g& E) s" x, c/ a8 F
cmtnum 转发数' p+ [' D3 R6 _

: \4 e: r# g8 P1 t, ~- Ccommentlist 评论列表,里面是每条说说
2 S7 r- t9 F" u9 B/ J+ k
+ X2 e+ G& s9 f  ^1 O8 I( q: y/ h的内容conlist 内容的一个列表,里面有两个参数,一个是内容一个不知道有啥作用,取内容的话直接取下面的内容也是一样的4 ^- J! k9 q% r. ?- X$ a0 ^
5 W& `, m1 m0 @
created_time 说说发表的时间戳
9 c! d( j2 h1 C) P
) F( q* W$ s( R; |3 pisEditable 是否编辑过
* f" D  n" v$ I; B3 S7 [9 _
2 [/ z5 k9 K3 l3 H- X. O1 |% Llbs 位置信息- Y" i8 I, E, d" Y- N( P. @) {
( K6 A2 ?: p4 {/ y
name 你给的备注,没备注就是昵称. J; M& [3 L" Y$ T
* }' s0 w2 w# r
pic 如果发的说说有图片则在这个键下面,但是如果没有图片则没有这个键1 y, P6 ^% k2 F+ f" @4 x
: G; o, Q5 c& Z
pictotal 图片数量,没有图片则没有这个键
/ X$ D6 R' Q8 [7 B' @/ Q* A; I8 u9 ]$ p' T. p
rt_sum 猜测是转发数量! B( C7 @4 q: ?5 e/ R" x- I" t

- L6 n" v; ^, m* v3 Osource_appid 说说来自的app标识/ }! g' O* u* d7 x+ k) _% L- X
! [' v1 t; u2 J0 e. P/ }# `) Z2 ]8 M
source_name 说说来自的设备名称
6 }3 z; o+ @. X$ F' f: A0 j, G# h' t3 p, ^
source_url 说说来自的网址
# H+ O- T9 v: Y( [
: y$ I5 a+ d( ~/ c+ ttid这个是每个说说独一无二的标识,可能是根据某些变量使用特定的算法得出的,直接使用即可) R8 G8 L7 j: [% M" y. S" d2 O( N
% k: w7 J( ?* N+ s! z/ q
uin 该说说的作者QQ. x0 ^- I% V7 p

- }' R3 ^/ q8 `) o; x当然如果是转发的说说,这里还会多别的一些键值,我这里未对转发说说进行处理,只是单纯地取出该QQ转发时发送的内容,有兴趣的朋友可以加以改进% c. I) @2 e8 u0 Z$ t7 y+ Q" @

/ Q3 s& S3 }& q8 a下面我们看一下这个内容的获取网址构成6 o1 y+ w4 l" P/ ]

: j& @  J( M8 l8 V0 O在Headers选项中可以看网址的构成参数+ X' c, |2 a- b5 f  F* u/ [7 A
8 t' }: g0 B- r9 f* t( F
经过尝试发现,uin后面对应目标QQ号,sort可能对应排序方式,我采取的默认值0,pos这是个关键参数,其改变决定了返回数据的范围,num是返回的说说数量,我选用的是默认值,不知道增大会有什么变化,读者可以尝试4 X/ [1 ^. I" E) F+ j

5 V# W* a; f9 f9 g$ h# @* |最后一个关键参数是g_tk,这是个加密参数,有了这个才能正确登录
, e! P4 J# k2 l% X% U6 Y" T' k4 n8 N8 n+ _7 ~$ j2 j; ~

6 u; N; L9 T5 s! _3 g' I% N/ z0 y7 N& v5 T# r
破解g_tk5 Y' N: _* k1 W6 e: B: e
网上的搜索发现是js,破解的方法见下图
5 A7 X7 w1 m) X0 r0 ~1 ?% m
: h4 H" `, P1 z9 u. ~, b: G9 d随意点开一个人的空间,进行如下操作7 Q0 o+ O4 k" k# y- }

8 z$ C) v2 c5 V1 q! w4 |0 s% j. j5 i& N9 g

* {5 |5 q6 @, [2 X搜索g_tk=后面的关键词
7 b$ l3 ^) E( X  J8 P& _. H' e8 K& |4 j' [

) b' F  a# U7 {4 A3 ~5 _
/ {0 o& A- C6 f1 v& D' ?" l4 k, P找到对应的函数,这里的函数读一下之后将其转成对应的python语言即可3 `, c  M1 c* U+ ]
8 W. I" x& J' \' ?& _
def get_g_tk(self):
% q$ g) U6 H, Y  |3 c2 j% u2 l+ |$ A p_skey = self.cookies['p_skey']
* s* x" e( P5 q* M6 v$ V* x0 A t = 53810 ^" U: v- K! [  l9 J9 Z. o, h* a
for i in p_skey:  a3 a0 _. J3 v' s% L  N
t += (t<<5) + ord(i)
7 R3 `+ h( ^3 _1 a6 X( o0 P. c, J return t & 21474836471 a4 S' t+ B+ C% v# U
1: j! |# {* R/ _2 L- q5 d5 c& e) C
2  T- P/ h* @8 O: ~
3
9 a( o+ Z6 {7 |4/ V& n! M8 }4 V) l- K* N- r& M
5
1 W" l' `8 j+ v, n; y3 }$ F: M& X7 c6
' O  V5 c; {! e; B, E; i说说的评论获取$ D2 \. d% c7 p4 `( ?
这里没什么好说的,数据返回是跟说说一起的,在commentlist的键里面,里面的键值对和外面的类似,这里就不赘述了,值得一提的是,外面的cmtnum返回的评论数是指单独的回复数量,也就是跟楼的评论数量不被统计,跟楼的评论在每条父评论的里面,对应键list_39 ]& r% e7 b5 B7 l  O+ \" _! v& g! M

+ X, ]9 t% f5 W! K* \# N" G0 N+ b, S) b; T8 O6 k( |; u2 D$ I( K4 |

" I* F* c0 |# G说说的点赞人获取
/ \/ P! v3 k4 F1 Z8 ^1 G3 s3 u8 C6 z9 n, |0 w' p& a6 O( n

% ?/ X+ N' O6 x6 M) [0 R* Q$ G框内可以点击,点击后
# H# m8 q% ?# l8 I/ u" g7 A8 u8 w7 V) g0 R4 a4 f  c

/ U/ ]6 w# O, g出现
& u2 N9 h/ ^& l4 o/ }同时右边出现一个1 c2 I; \8 g/ W% s# Y* S

. L' T* U2 _/ i4 G, W* I* y- c- g* h
1 [/ y3 ^  y" X8 c+ S# B
这里对应的内容为; c) I' I5 F( d! v3 r4 }
; k/ ~: W( J# U! f7 x7 T' B2 A! V
is_dolike 我是否点赞了/ E8 U# T; k, t" _
, k8 Q3 [, T5 i$ c* d) c- x( w
like_uin_info 点赞这条说说的朋友的信息(除我以外  U" B; N. \: {& n. H' |

9 u; x9 {: K1 z8 H( Etotal_number 总共的点赞数量
( q' }% A4 m; @1 _5 A. s1 i) O! _8 m" O6 d1 T
每位点赞好友里面还有一些信息,我这里就没有赘述,那些键值都看得懂
, u( f  L! o: g2 \' x; s
  o9 N8 W( ?9 U$ _* a. u! surl参数构成) C7 j+ w- p, j* `0 y0 @
那么还需要知道的就是url的构成,老方法,先看headers
7 x, S8 U) K2 j4 V, ^
: a9 f4 o# ?' o% \- R' ?
- ?4 Q- ^" [7 i( ?4 J+ K9 [+ x' W: X9 K  c" c' U* ~
那tid在哪里呢
# T9 F$ F/ \" u' ~
/ S3 _, ^' I# i* X0 I5 Q3 ~之前的msglist里每条说说底下对应都存在一条tid,这里就是它的用武之地了!; Q! i: L( ?: V0 n. l) O/ Q/ ]
; n% K1 B6 g3 Y0 I! z9 ?* B1 N: G2 o
好友列表获取5 W  j* S( j, A8 w
我在网上看到过很多个版本# G: O( k4 H1 N
+ O, J% R: u" _6 a3 {" h
我自己也都尝试了一下,以下的版本获取到的好友信息与QQ好友是最一致的
# L' ~/ X; H; K% i: {% v3 J* {0 M( D! R
进入自己的空间后在设置中点权限设置
8 A7 S3 [' g! n/ B/ I" I8 a/ @- E% X0 M1 u) Y& J  l$ \) i
- j+ l# w, l! m

7 g: u' G/ |; f# T4 C7 |0 `. A
' ]. e3 Z, l7 u' D- c% x* b* c* f* m* J) I
找到对应的项,friendlist里面即是,但是只有50条,如果你点开了xxx个QQ好友并向下滚动后查看url构成
# @) V# y5 E0 z& @+ v5 r4 f7 f8 g. _6 X' v0 ?, X
就会发现
4 A8 g# @  ?/ \3 ?1 t* }( }8 x( t3 `+ ^" J2 U8 r; o1 x( w" \

# b2 E4 p2 E+ F: T: }: r# }9 Y1 b* M7 _, }
offset偏移量用来查看更多的好友& J" ]- i  Y6 D7 Z
8 d  V- P9 S* T" X4 X4 S. H# i
,如果是最后一页,返回的字典中的键end的值为1, M. ]; u1 e; i; J' L$ C  J7 ]
$ f4 |' ^5 P  j
数据库的存储
" V5 q; r. r; J由于对数据库的使用不是十分熟练,这里单纯只是为了存一下,有很多弊端,例如图片的存储) G3 E0 ]. x( \8 N) u4 l6 V% T( C8 K5 L
1 o0 J$ Q+ j4 E) A4 }! i7 m
而且用的很丑陋,这段代码可以忽略# E3 v: |7 Q$ \' g4 q& u; t

: I7 B% `- N3 m, i2 z! t3 @, h" B$ rdef check_exist(self,uid):
3 I0 G; J' r; ` cursor = self.conn.cursor()( T* ~( P$ h# [
cursor.execute(“show databases”)
# j' G4 j* U) ` content = [i[0] for i in cursor.fetchall()]
: F9 H( R* v% C+ h& P if uid not in content:
; P$ O# ]. L: Z8 T6 a+ L! N cursor.execute('create database '{}';'.format(uid))
% M2 a' U$ q8 o+ ? cursor.execute('use '{}';'.format(uid))
6 ~& c4 b" p1 ^( | msg = '''
- j# y2 I$ \, T$ g9 k" c% ?" a 创建表 msg) V* @& @# Q9 w; _) F7 }2 L

- ?7 e5 X* Q, ]9 }/ @) J id text,
/ j& Z' V5 }( j name char(100),6 N4 v% p4 A' B
content TEXT,4 R) @1 v' o8 }* |  X2 N
createtime timestamp,
. j  ^( j' K4 i+ k tid char(32),
5 U) X7 |2 [& Y4 P( E2 A location char(32),) `9 j. [# x+ n5 [
posx int(20),- r8 M, a, o- S
posy int(20),5 s, n4 u% Z1 }5 R+ l2 j3 z6 P
comment_num int(11),7 N0 v; i# I6 U
like_num int(11),
  C! y7 F$ S. ~1 t, R5 c pic_url TEXT,
" V1 ^  o2 {. f8 d: a, u pic_num int,
# V+ V# {+ N6 T9 s source_appidchar(32),6 |* d% }, }, ?  d# A7 a/ G0 e
source_name char(32),
+ q- k0 L% P$ d, A, T6 i) P is_tran char,
2 i; K  \* o) \" N7 \ trans_num char(32),
* x0 e6 E( v! u9 R9 r trans_content TEXT! ]" F& _0 D  Z) V/ V7 n4 C
);8 h1 G, P9 I- s$ t6 s
'''0 |  Y$ M8 S& T7 N/ M
cursor.execute(msg)7 g, x# w1 `& P4 `2 x
cmt = '''2 Q5 b( X' ]. t6 M4 g3 @- ]
create table comment
) L+ r  L$ F2 E) o/ q6 e/ ]1 b# Z. A. |: d# P8 p1 Z+ o
tid char(32),3 w5 |! ~8 B' _( g$ g
id text,
5 |# M- O! ^3 m name char(100),
# o/ L+ Q$ _& R: D" v0 H4 F1 t* W content TEXT,2 P% X8 v$ r* Q  C
createtime timestamp,
) d. ^) X8 _  g reply TEXT! d) `9 Z" ^$ b4 E5 }9 c) j" R5 H
$ O! A( d: i% u8 K
'''
# t* c: L/ Y2 E1 E2 r$ r cursor.execute(cmt)
0 a( I+ C% U$ C% U) A like_table='''  k4 k( \( w! Q3 u, g
create table like_table; [5 _5 R. `5 v" Y" H! L% k" h

6 h3 |# A1 I0 i4 t tid char(32),
% [- j6 ^+ k9 g id text,. r$ S; j0 r( h% j3 l& \2 s
name char(100),/ v; b3 [( v1 F0 T6 O
addr char(32),
+ R% i7 `' ]3 d7 W8 _ constellation char(32)、
7 S9 Z1 n$ d8 sgender char(4)、
" c7 W( j- p% D0 E  _) T/ q  y- Vif_qq_friend int(1)、# G( @6 _6 m$ n5 j& a  ~4 @% J
if_special_care int(1)、
# t/ T7 O9 }. P2 E( N  H' Jis_special_vip int(1)、' h& @5 y5 o# J. \
portrait TEXT
% s( o/ ?4 P7 {1 a5 F/ ?
9 P! H8 W* R/ I/ A6 @ '''
5 ?+ k7 D& N- Z; e! i cursor.execute(like_table)
2 d: q: T8 D+ u6 h* d4 U$ \8 N9 W* V self.conn.commit()- n5 J  ~) R+ v% c4 k
return 1
$ G5 v9 G+ R3 _ else:$ E6 }3 S8 {3 e7 G3 i
return 0* O& b5 V. A2 w7 J# E

( m- t5 A# S  B; ], K+ E————————————————
, h5 x4 O; U7 U2 h9 q% B9 T
发表于 2024-10-9 11:21:01 来自手机 | 显示全部楼层
大佬可以帮我看下嘛,有偿
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

QQ|手机版|小黑屋|☆我要吧☆ ( 豫ICP备13016831号-1 )

GMT+8, 2025-12-6 05:04 , Processed in 0.075059 second(s), 18 queries .

Powered by abc369 X3.4

© 2001-2023 abc369.

快速回复 返回顶部 返回列表