7 z6 j# B/ `0 l3 }' \) }" j( x+ V5 C: W j% U2 Q6 H S
在爬虫中,一个请求很久没有结果,就会让整个项目的效率变得非常低,这个时候我们就需要对请求进行强制要求,让他必须在特定的时间内返回结果,否则就报错。+ d/ Z: g3 E. \5 K9 e
; J% Y) g4 K+ O1 v' e
; I p& [+ L; `) n+ S文章目录. ]+ ?( e5 B# Y
requests , i) @/ h! B) k Nrequests基础( Y% u+ ^" A$ ~1 W
requests模块发送get请求/ E, K$ Q3 `/ p; x) O/ y
response响应对象8 R; y( s" C8 b: C' H
response.text 和response.content的区别: p3 g5 ~3 ^& _! c, e
解决中文乱码7 P- [' @! \0 y& t/ p
response响应对象的其它常用属性或方法7 k0 q, b/ N, f% h$ y9 y
requests实操& I8 m, b ?7 p1 b2 g; j/ A& {
requests模块发送请求! y6 s' M* X$ r6 a6 W3 D1 o
发送带参数的请求 2 b O3 {3 A8 a/ L* u% |超时参数timeout的使用 3 g) m* r6 n, u, @) ^4 `requests发送post请求的方法( X$ h" {7 M, B* E. b6 p
BeautifulSoup3 x, o' B0 E( I. f/ {6 w* J5 p5 B
常见解释器的优缺点: v3 T4 [ M3 h: q
常用操作 & W# A0 H5 N/ y; U6 f9 B5 b几个简单的浏览结构化数据的方法 : F/ t) g) o3 j% F7 U从文档中找到所有的< a>标签的链接6 _4 L: C O9 m8 w! n7 q( a
在文档中获取所有的文字内容 ' y& ?/ J# |5 l1 I通过标签和属性获取 ]( M* i7 o! l& I6 sName属性3 Y; b1 y! z( H0 G! `
多个属性 ' ^# Q7 r l( `; |) @多值属性: f6 b% m1 V0 w* d0 _
可以遍历的字符串+ v, g# }; g* @" {1 ^/ l
注释及特殊字符串 # {' V. l* i1 j$ @6 J# f; i* z遍历文档树" E! v4 `& p- J+ l
子节点 5 h5 e! ]7 d2 C2 _5 o" Z2 ~5 qfind_all方法+ E1 n( l# Y+ @- |: h
.contents和.children 1 T) Q" }& r2 n+ zselenium3 t9 Y2 W$ T( H V7 E
selenium介绍2 V; |& u( m6 h" v) a
chrome浏览器的运行效果8 h6 m( w) z& j$ \% a# A7 [
phantomjs无界面浏览器的运行效果 ! `; A8 ~+ N6 {- b! w/ M ?selenium的作用和工作原理2 K) A. D0 B/ L$ }! ~ Z2 ]+ `
selenium的安装以及简单使用 7 l$ A8 w/ U3 k5 O: lselenium的简单使用* m" t o/ o; F+ l4 o1 P
lxml % o9 f* d5 R# [: x常见解释器的优缺点5 B6 l1 O, h, J6 S! m
; S0 w+ b3 | g: E3 o" S" S
! D: D' T1 i0 A U. G7 ^1 {" K1 {) d) C8 Y$ _ 0 `% n5 v4 m1 C5 _5 p常用操作 ) j; r. |' m! @% T; _; {安装方法 , i2 k2 e2 u, g3 B/ Z. m, L p, [: x: s7 o4 C8 F8 A/ p; s4 R0 n: F) L, l1 o
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple beautifulsoup4 $ F! G0 d! t. e7 V9 S n1 ( A, R# ?, h- W4 Q1 i' r: | T导入即可- t! x9 q# `3 ?# U& b# k; ^
1 n3 E8 f6 }5 N" g) p7 |
( ]) D" F8 u& x
from bs4 import BeautifulSoup ! F# N/ J) `1 ~# E$ T3 b1 ( _ @, Q. u0 v6 d* {; d" n. Mhtml_doc = """$ O* D. t, ~$ q2 T/ A% {& }
<html><head><title>The Dormouse's story</title></head> 9 Y& [9 i" v" e8 n: `* h<body>: h3 d3 Y7 a. p ?
<p class="title"><b>The Dormouse's story</b></p>& V E; Y7 x5 c' w
9 W5 D$ O9 V, T9 @% f6 I' m' \. Z3 O9 i6 N9 _7 C- t
<p class="story">Once upon a time there were three little sisters; and their names were9 u( D7 h. y0 H3 F6 J) M
<a class="sister" id="link1">Elsie</a>,9 C$ l- p8 o3 i" n6 J: L
<a class="sister" id="link2">Lacie</a> and8 m! \1 d) Y* a9 K, ^: H# l
<a class="sister" id="link3">Tillie</a>; 4 ~5 U3 ]) M8 v+ g4 Kand they lived at the bottom of a well.</p> 1 e! k! E' y, P: F }. c5 x f! l; ?& h9 x9 @6 b
* @0 |. G" w; D2 i* q' f* C; a
<p class="story">...</p>" x' o% P7 h( p* f! z# b
""" ; |* o% H( `0 l( P# b7 d3 i) s1$ A& R; z( p0 H- M1 L4 t( [' K
2& V4 Y! q& _( D/ m P3 A3 g
3& O) z6 h8 U+ T/ v
4 / G/ ?$ `; N7 X* c; o5 W5 7 \# P" J- n+ A$ T. u" I9 M63 o* m0 `8 k8 h+ U
7 8 k+ j6 ~" H, d3 P' m f8+ p* z; h+ Z- U
9 ; a- A2 a, {! }5 p, Q, ~10 ( s) }+ w3 t& r' l- z: e11 & i4 L( K( n; N) C* x* F& n+ L& ?12 1 R! ?% o" B( O13; g! W9 O$ A; Z/ v4 G* F, ]
soup = BeautifulSoup(html_doc,"lxml")! _) q0 ~, V1 M
1% I; v% n8 E/ T5 X6 c* N- c# F4 e; b& W6 ?
几个简单的浏览结构化数据的方法 e5 Q# g6 ?' f2 d6 s3 E# [) F
soup.title 0 u# I8 h j% F& L17 @! J: x$ A' @+ Q7 D
<title>The Dormouse's story</title>5 J* w7 d* y; F& }( e
1* V H7 O: r/ ?0 K0 d4 ]* u
soup.title.name / E- k6 H0 l4 [% t" e! }) \5 Y1 $ R7 s( l6 @, m'title'0 p* T& e+ K, `; k8 C3 {: k: r; c
1 3 t' g" R1 u; u7 N+ w" E# x# t+ C- ysoup.title.string: j. f- Q4 S" l
1 / z9 u7 t- o% B+ ]"The Dormouse's story" # s/ c' e* p2 v) Q0 ], t( I1 * Q' r) v- d1 G: I) M- p5 Jsoup.title.text 4 r. R5 v0 B3 r! y" L0 f13 j6 s% s; u: {7 q, ^0 _
"The Dormouse's story" ' w- L; Y$ C- V- s7 d$ I1 ! C- L+ Z5 p t- g0 Asoup.title.parent.name % T* X9 M- y1 N1 k- y1 & P+ j* I5 S; J( a. U2 f+ Q3 X# h; V& o) M'head' ' e$ u Y# U. [5 H1 8 e: N6 C9 w# c+ `8 G' n( e \soup.p* l6 i6 X! u5 L0 R v; R& J
1, N6 h; T' `0 e6 l) n4 K, r5 N% j- M
<p class="title"><b>The Dormouse's story</b></p>4 a8 K7 X# ~" G1 H' ?% s
1 , Y$ F) @/ a Y4 o3 T" Hsoup.p.name 6 Y! f% M2 ]7 q2 p3 A; D: f1 : E& Y3 w. B$ y; {! Q'p' ; ~: x, b: x1 |9 t/ t! x1! q S' W, X7 N. r) d5 ^
soup.p["class"] ; I3 M1 W& `/ d9 U7 P: a5 N7 J10 S: R- g" {0 A4 h; h" p
['title']0 k; ]' P4 W4 M/ r4 _) n
1 + U" M; w" K7 C y# g2 Q$ Asoup.a 3 e4 v/ u4 u$ u# c4 L0 E9 D1' C0 ?, X5 \& {2 Y
<a class="sister" id="link1">Elsie</a>, m! M) `5 a7 J5 r
1: k3 G* [ }0 \( z; Z: z: D
soup.find("a")3 `/ B3 C& v. V8 X) {+ F/ N
1! }, s( ]/ O4 q
<a class="sister" id="link1">Elsie</a>; {/ u! r2 |* d# p# H+ I
1 ! N! M$ J1 S; ^2 h" l: O: `soup.find_all("a")8 q* `1 i+ F: i: U
1$ D8 P" s# J s) ~1 R2 O6 m2 B2 a/ V
[<a class="sister" id="link1">Elsie</a>, ' y5 h2 q. @& G1 |2 N W <a class="sister" id="link2">Lacie</a>, , k; _8 o; B( }* _6 E4 g <a class="sister" id="link3">Tillie</a>] * j- R# H. W' d$ D, X- _1- e( E' @# f, R6 ~& y; b" x7 l
27 K! [: I8 o" a: p/ `
3; S1 n# C: f1 i
从文档中找到所有的< a>标签的链接 - i1 F: x; @; ?for link in soup.find_all("a"):4 k' A# A! j* U% O/ S/ c0 O2 J
print(link.get("href"))" c9 ^2 W8 o2 ~- }( J* [
1/ }3 t+ O- @; Q7 r
2" J, Q% |' V+ [8 l+ n. ]
http://example.com/elsie8 G: a, ^7 f) b6 [+ f% H. D3 I6 }
http://example.com/lacie ( U7 a1 f k* N8 O- Yhttp://example.com/tillie / N5 s! P- Q- V0 w0 M1 ' X- G. `1 h9 W" G: j- {/ K1 q4 Y2 8 V8 s, ^. Q9 [7 w3" N. z! }+ L) o# r; Z5 T
在文档中获取所有的文字内容 3 C3 q9 b ~5 d3 K+ K$ cprint(soup.get_text()) 7 Z7 j: F2 @: w3 `1 V5 b1: y3 j1 c V) Z
The Dormouse's story + W" F# N1 N9 Y) I. B1 f* |6 `7 T6 U! y. I
* t/ \/ }! I( ]8 H1 WThe Dormouse's story % C( g: g2 ?, c" kOnce upon a time there were three little sisters; and their names were R, h. [8 v* g% c5 U+ CElsie, R6 c+ X1 J% k3 A% VLacie and 9 S2 k! z! y7 h: [0 d8 aTillie;0 F7 m' e& X; F
and they lived at the bottom of a well.) h8 K' M; g8 B2 p3 x! ]
...% g) H8 s) Y0 y" }6 _! s( H4 |
15 [! m, ?' [+ x3 h- Q3 ? b! c
20 q/ d& P* h) c8 }# _0 L" w! V
3 4 d4 h: d7 z( `* S& y4 M# w4 + N: G4 B- }- n+ z+ G* \7 J+ H5( R8 X2 a0 y1 w( t& }$ U* T
6 - E- x# T! n3 O( T3 ?7 ; u4 z6 G E* o M9 X+ o0 N+ N8 / {4 U! B' j1 ]& f, b' w98 H* O) i6 Q" K+ f% S: w3 R) r! p! r
$ B! @( @7 E) ]% Q8 c; Z* E/ a0 J6 W
" U& c: p1 S: Z+ i$ d5 u6 {( k9 h0 E9 i2 [* B; l0 u
通过标签和属性获取 : v: N6 _+ ^7 r. MTag有很多方法和属性,在 遍历文档树 和 搜索文档树 中有详细解释.现在介绍一下tag中最重要的属性: name和attributes! i/ h# }% [ c$ f
soup = BeautifulSoup('<b class="boldest">Extremely bold</b>'), i- B; _# a4 }! R5 K
tag = soup.b ) g+ b5 \1 J# i3 jtag & p; [5 O ~3 {0 z8 J1 5 a7 Q0 a; i% u" Y. _7 I$ B. P26 [* O2 a: M: C. @1 E
3 2 z9 R# N9 N% J% m# R' g<b class="boldest">Extremely bold</b> 8 U3 T' d' q+ ]+ E( E8 X9 |1, o% b( I3 D& _, M/ t# N/ k1 F% `0 s
type(tag); T+ n% z* X: ~% S! O
1 * K6 T$ N2 y. S7 G' Lbs4.element.Tag3 a3 Z' X# l1 B$ |# T; p
1; c2 ^$ I+ l5 M1 G) q: _4 M" |
Name属性1 I" @& }6 ~- e1 J' L
每个tag都有自己的名字,通过 .name 来获取:/ r V% l8 H$ |- Y' B
tag.name% Q! u, S3 S& Q' j
1 @7 B$ k) u2 f' ^- h/ _6 O1 m'b' 1 P; b1 T/ t( Q1 F" d7 s8 J1 ! \, N9 T( o: J6 W1 r$ S. `如果改变了tag的name,那将影响所有通过当前Beautiful Soup对象生成的HTML文档 U) p% [' D/ {
tag.name = "blockquote" ! f% }( ]8 v# u8 J3 u' dtag 9 h% ^" f1 B* m/ v$ i" m1- X2 E/ {9 {# A H. w2 L
23 S+ i5 ~+ ~) F! P- z X! B; [
<blockquote class="boldest">Extremely bold</blockquote>9 m* v: @! P7 u7 G, V
10 {7 c% v) ]7 w
多个属性 y- W* w: l* \: F& _一个tag可能有很多个属性.tag 有一个 “class” 的属性,值为 “boldest” . tag的属性的操作方法与字典相同:/ y$ r/ D, f7 D; D4 n; X
tag["class"]0 A! h% P3 X C7 e6 W
1* M2 @1 b! \$ O) @2 D/ w4 ?: L
['boldest'], @- L: N8 \" H# ~3 @
1 8 h4 o' a9 W' d$ gtag.attrs ' t: p3 i% D# W- x' `. S5 {3 A* c14 Z6 R1 x2 D6 z" ]. r
{'class': ['boldest']}) G9 ~1 e) F/ ^' h2 R& `; N
1 , N& T1 r; L. t- L/ mtag的属性可以被添加,删除或修改. 再说一次, tag的属性操作方法与字典一样 . J- E& p) w) r( y2 ctag["class"] = "verybold"3 v; ?3 |5 \8 Q6 t p" D: `1 d
tag["id"] = 1, }, u) u4 ]. \0 ?6 W: Z$ s( L. t
tag % `6 _5 f" m( z6 b13 ~) T. D" s. m7 U
2 ' A3 b3 N5 p* k( d/ Z3 , t) I* R7 |( x" B0 _* b7 m<blockquote class="verybold" id="1">Extremely bold</blockquote> ! e3 x8 z+ Q" F: \% y: w16 a t/ o7 U" Q. J
del tag["class"] ) A! t c: ^3 R3 {) y# }tag / Y0 Y1 Q$ P; k: t1 5 V% y8 I! s; o6 C* P; W9 w) _2' w1 v* V a" R4 h3 \+ J F
<blockquote id="1">Extremely bold</blockquote>1 D0 y& [2 [ c1 o
1 2 L8 J7 C/ H0 b- r4 G多值属性7 G) J+ D6 Y5 ^; m; S& _* e/ Z
css_soup = BeautifulSoup('<p class="body strikeout"></p>')& U% Z3 M9 I' I' q# M5 H K; c: i
css_soup.p['class'] ! [' p+ D3 q6 Y1 / I H0 a: P$ h7 q: ?2 , A& ]# \$ J8 o+ c- `4 j- x['body', 'strikeout'] , }/ H; N' E& |8 Y* I# O; j1/ q& u+ I, d5 z5 d V F
css_soup = BeautifulSoup('<p class="body"></p>')1 }9 I; z( `; u8 w6 i7 h4 [
css_soup.p['class'] 9 a( N# X; c B6 t6 \# q$ w16 s. @2 P1 q3 L6 \ o: q
26 y+ z( `; d, g5 H9 b& J
['body'] ! V8 b- T$ t: t8 Z# k, `- y" U1; I" J, s5 _, o8 z, p( c
可以遍历的字符串 % g% T+ t/ h. Q u- b字符串常被包含在tag内.Beautiful Soup用 NavigableString 类来包装tag中的字符串: " e' o) t% |7 \tag.string ' u% \: g( I- J2 m7 U. l3 s18 q2 V8 q# W# L& m. h
'Extremely bold' * f% e8 g4 Y5 t, ]' C12 L+ [: B8 O* ~; D/ W$ G
type(tag.string)7 Q9 w; R" y" o
1 : U" l% k2 M) h- ^bs4.element.NavigableString @% v. v7 J9 p/ n1 l
19 D6 O5 }0 k) ^/ G
一个 NavigableString 字符串与Python中的Unicode字符串相同,+ |4 d. b. _9 x4 L4 b U3 U& p
并且还支持包含在遍历文档树 和 搜索文档树 中的一些特性.! d: c+ Z h6 @$ i
通过 unicode() 方法可以直接将 NavigableString 对象转换成Unicode字符串: $ w( Z6 ~! X$ M1 I b( V3 P2 G6 I, D! R# i. e: s
3 G- m1 c$ \- |- U
tag中包含的字符串不能编辑,但是可以被替换成其他的字符串,用replace_with()方法 ' A- T }4 d: F! ^. J. g# A& R1 m' V5 v8 Q7 B1 ]! ~
6 _3 L, ]# g% y( s4 y
tag.string.replace_with("No longer bold") 9 k2 k; ]% Z+ O6 Z8 S' L) Ptag L3 e4 j& ~" T0 }2 P
1 " i8 K3 K5 `% `, W W- M7 L' p" T2 + _: W: M' C- V, c) }# { ]<blockquote id="1">No longer bold</blockquote>2 k5 S& w% e- M. |
1 3 a! W. d# W1 k2 R6 N注释及特殊字符串% O$ d8 U) J8 q7 g+ a
文档的注释部分 ' O+ G e% m$ h2 E) {2 c9 `markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>"' t$ | b; \: J; ]
soup = BeautifulSoup(markup). {. j, N: @3 K3 Q, u* ^4 E
comment = soup.b.string9 m# O, `' x5 o
comment & k7 F" m5 g8 p1 S2 ~' _0 W- N- a1 g! a4 P* v8 B+ z7 \/ A22 Y9 C0 h* z/ u0 w( P p
3 ! m Z7 b; c. W! c8 Z+ t4 3 \' L3 U, q, n# R- T'Hey, buddy. Want to buy a used parser?' , d* A+ f; g" y8 g/ M7 h; w1 : @/ m* k M/ c, m0 _' l: T) Stype(comment)3 C3 x+ N' {% s! \
10 z( a8 I3 k6 d, g
bs4.element.Comment6 B; C+ I2 ?1 i9 F
1. |' A* h" u" D* }+ }0 {
Comment 对象是一个特殊类型的 NavigableString 对象: 8 `4 F, Z: Y; ocomment$ ?8 E+ J* W" p% j+ X
1; B4 l4 W. ~! X% D3 K
'Hey, buddy. Want to buy a used parser?': G2 r4 @2 L# z
1 5 p6 ~6 q/ p2 |5 ?但是当它出现在HTML文档中时, Comment 对象会使用特殊的格式输出:$ B$ M( J% N3 d, X; ?# R
3 _& a) l; W8 k3 v9 I+ r: z
u- x6 d8 z+ _2 zprint(soup.prettify()) Z2 w& y& S) i0 T
1; t/ i3 T3 X3 W+ N+ }: A
<html>( l7 G- k1 x, A2 \) Q' Q! C+ X0 _
<body> ( U3 R$ d) T: @0 e% F1 |, y) q <b>1 k6 P P1 O3 @0 y: O
<!--Hey, buddy. Want to buy a used parser?--> c5 N7 \/ ` p- D </b>6 a* D+ J; c3 d, q
</body>7 N6 ^( r9 q3 ]( ~2 l" A8 {
</html>& Y6 j+ J- a \) j. S
1 5 J3 ?% X7 z3 G8 o$ c1 w- H2: U( V2 k+ G7 B2 t, y
3" j+ _* A: n4 G0 v F. g9 N
47 p0 [8 j. p4 X, |
51 M, _4 c$ _8 w3 I0 [" P$ `+ M2 h
6 " }$ F! P8 N- x0 c! h# s7; @, t" S; X2 a% l# W/ E+ t- X
from bs4 import CData8 f3 d8 l& V# T9 f
cdata = CData("A CDATA block") 1 F* t$ a2 B, A# vcomment.replace_with(cdata) 0 b% U) e2 p0 s" N/ n: v) X% }print(soup.b.prettify()) 0 v9 F0 Z- I: H9 y+ Q9 f12 W6 \9 P" ^* G- L- W9 K( N
2 9 b1 q; @9 _# y/ e2 C3 # d D. v* F/ }3 n2 e6 K46 F2 e% x1 R& T6 B" [
<b>; f& Y+ G( u' F' k
<![CDATA[A CDATA block]]> ) B! ?" p( P: y1 d3 Y' U# P</b> * x; n8 W$ H2 C( ~9 t# ^11 O* |7 I: z# i" b5 J
26 i h, E# A$ @ z! A: J0 i* O
3; h+ @" U( `$ F* Z
遍历文档树 7 j+ L- G+ j) d$ q6 E/ g c7 thtml_doc = """, i/ w& s+ b1 n, d# i) `3 x
<html><head><title>The Dormouse's story</title></head>0 B3 o: M; H& G4 U+ d
<body> 8 f" X5 C) N. C6 v3 O& c1 G<p class="title"><b>The Dormouse's story</b></p>5 f n# W7 z3 G* z* w3 X' l- e
% x# Q) e: {5 l/ h2 ]& o3 f% \2 w2 F% v# { s: h
<p class="story">Once upon a time there were three little sisters; and their names were * }$ d& r) u9 m* @: W<a class="sister" id="link1">Elsie</a>,2 v5 ?8 L3 p' A: V( ]5 D
<a class="sister" id="link2">Lacie</a> and $ x3 e7 s( X: F6 r p+ k) a/ O9 o<a class="sister" id="link3">Tillie</a>; 3 b6 K0 p2 T& d' C, {9 D0 t0 fand they lived at the bottom of a well.</p>- O% L4 F# D. H" s" f
! G) h$ n4 j* Q% r) O, i- n" @/ A! N5 X2 |
<p class="story">...</p>: m/ c. S0 _3 x
""" / \6 w/ E3 _1 E! F; \1 # n! H r0 Y1 h1 ?& y- I: o$ j2' V5 v- X9 y0 C8 U* R
3 , x/ }+ T- D2 _' w1 [. M A8 H42 _" N( r% e- s: C. q' z+ X
5( S, C, a, Y% q/ K) f
6 7 F3 G/ l: d% z$ C70 b& j0 N' N1 h0 r( W% B. I) m& E
8 . j" c/ y" j! e/ ?1 P: d$ }0 P93 E" e- G/ ^: ^: n3 g7 ^
10- R/ I- A1 {9 c) S/ i( Y
11- g+ u. q+ {+ t. G, p5 [; _
12 . x: g0 ]8 I9 B13 i' A U0 a; G! P9 k# p% k9 `from bs4 import BeautifulSoup, Z8 ^- Y E) q+ Q; A# U, u$ |
1/ l( x K, c+ s- z/ \/ X
soup = BeautifulSoup(html_doc,"html.parser")* r& B1 `& I: D8 F5 l
1 8 I6 ]: X* b; ^, W6 A4 `子节点2 K$ |1 @! E8 J4 }" }" h& {% f
一个Tag可能包含多个字符串或其它的Tag,这些都是这个Tag的子节点.Beautiful Soup提供了许多操作和遍历子节点的属性.5 [8 w" n$ L0 B9 W# e- q. p
( {; p& F2 d( L( T( R( h9 D: V0 b% A$ B: j2 b. ] b2 f
soup.head 7 T# W( q+ Y1 b" ~1# ]2 Z% O8 E2 w
<head><title>The Dormouse's story</title></head>) X( v: O7 W8 m9 u) p6 n" t
1/ H( W6 u( q( j8 O
soup.title9 [6 o* e7 \$ ^ o. f
1! H' T$ d* L4 Z. P
<title>The Dormouse's story</title>- Z) Z4 X% f2 o. B
1" ]( Z& p3 r7 y; ^; Q! h
这是个获取tag的小窍门,可以在文档树的tag中多次调用这个方法.下面的代码可以获取标签中的第一个标签: % ?* X9 Z5 k( {) s* W : O, Y9 F8 L d9 G$ a - Q# E( j3 K+ L# _soup.body.b 7 `, j$ h# C0 a+ i/ u1 $ |$ h( F; y+ ?3 f M<b>The Dormouse's story</b>; N) e* q9 u, X- `+ }
1 0 [- r# E% Z9 p. w/ Q# p通过点取属性的方式只能获得当前名字的第一个tag:4 m4 k+ ^# P2 L5 d9 Q1 J
5 f1 t* G2 u' n
$ b3 b; T! m6 H: Q5 {: Z; asoup.a # p7 K, \! ~" D7 n- }2 r7 n15 U( n6 z# A5 s" F3 U7 x, ^0 Y
<a class="sister" id="link1">Elsie</a>$ ?3 c/ H7 M7 [0 K( {! O! h
1; s% H3 x/ J' I- S- T3 _! j
find_all方法/ m: K0 X/ O' v, ]$ M) H4 j
如果想要得到所有的标签,或是通过名字得到比一个tag更多的内容的时候,就需要用到 Searching the tree 中描述的方法,比如: find_all()( P3 h# Y3 h& l- l; {; ~+ N* I7 B
9 \: F, V8 _/ ~$ o: i% g+ G! C! ~. v, D, L8 y4 |+ {% [' b
soup.find_all("a")$ h9 Y( A& h! ]9 e+ c* c; j; ^
1 - f1 K2 R. M/ M. U2 G5 s[<a class="sister" id="link1">Elsie</a>,: d+ f/ z& i; l) k" l
<a class="sister" id="link2">Lacie</a>, 7 K$ S0 U8 N* E3 H# H3 @9 V! ] <a class="sister" id="link3">Tillie</a>]3 V3 H$ ~# ?5 q
1+ K5 e n& m$ E4 @
2 5 {7 c1 b6 Y$ r& O3" \9 a1 d) J* c2 `/ u
.contents和.children / R5 p1 x- k; f% `head_tag = soup.head 3 H/ A+ l; q6 ^. i& Q6 q, _+ u. ?- dhead_tag6 n6 g/ t$ S- N ?) w
1 4 J2 b/ X' }4 ^/ i2 M* n2- a- y e) l- D: v
<head><title>The Dormouse's story</title></head>( J/ x; T' Z. g5 j
1 # J7 @/ c2 R2 Ahead_tag.contents 4 m" D: p# ^% N+ @8 |( s8 p1$ b) H4 C# A" A: q% ]6 N
[<title>The Dormouse's story</title>] # y6 u4 Y. I; _5 T+ X1, Q* S2 [8 c7 [, O3 s
head_tag.contents[0] % f4 _1 Z1 K& Q1 K12 _2 }! c; [/ {, k
<title>The Dormouse's story</title>7 h# W+ a4 G7 w, V: I
1 / H$ d5 g4 D* c) L9 l+ I8 Whead_tag.contents[0].contents- T- a, \8 L/ ^7 S
1 . B/ ?, r' u- c* m8 z" G- O["The Dormouse's story"]% Z! }4 Q4 x' y/ _1 J6 [6 X
1* J" A1 R p" E* q* H
selenium7 p4 @3 J( a; r) n
3 ]& r* I" `0 o4 M0 J: u& B9 e1 Z
; v1 p3 H$ y- E3 [ I9 u6 N# Z/ Y) a. E3 G" v8 V. j! c
( ]4 ~9 ~: P. f1 M3 z# uselenium官方文档 https://www.selenium.dev/selenium/docs/api/py/api.html% \. x. j- c* }) I