- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563328 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174221
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
% Z) L* I- T# f6 R7 X6 R k
# f9 G( q7 }) `6 n @
; w0 X; ^" F- R* g9 G: g/ B手把手带你5分钟搞定爬虫(聚焦爬虫)
5 c# ]* R4 g) S& ]: T, O* G4 p) T4 G7 F' C
爬虫的原理
3 y- [, E( H8 C6 \ T5 ]$ d
: c1 ]! e/ V( l6 ?2 j2 \对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫1 g! E! K3 A- j+ m8 G( s6 u$ Y8 u
把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味
; S2 _: {; [& Y0 a3 F9 E/ s5 s6 y$ J所以说爬虫分为三部曲:$ c+ H/ ^% D+ j6 [
1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)) W; ~6 s" k5 R/ H4 q9 P! k
2、去找到你喜欢的食物的位置(得到目标地址)
. n: p# J( ^ A4 |9 H/ s$ {3、把食物搬回家去(解析网址,获取数据,存储数据). h+ g$ o8 L0 f+ q6 M
它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)1 e7 a" z% D% N" o) e% h, {2 F2 b
a、导入需要的库 requests
9 }/ y# V3 D- }
; L1 {0 K# Y' O. j& G @/ x2 k2 [import requests( I5 h e' P6 a6 f9 f
1, x! u9 f7 C+ J6 J# c/ O/ {" F; n
b、明确你要获取数据的网址(这里以百度网站为例)
& Q9 P0 [- N; U+ V/ Y4 s$ X, m# U8 R
url = 'http://www.baidu.com'1 d' A4 i2 c% y6 M
1
' d6 f" ^- _1 e6 a/ i( Fc、创建请求& e; e3 l7 o" U f4 \
9 n$ e& k# t# @: tresponse = requests.get(url)
2 _ Z3 G/ o' P3 b; V1
( f* F7 Z& F6 |: _3 Fd、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
; E q$ [8 b/ P: f" ]% B; a* H: `+ P) [. G
print("状态码:",response.status_code)' u" b g0 Q$ ?
1
' Q3 N. ]1 @( A# Q; @3 I+ H4 i当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url# e$ s: P6 ]# Q; O
e、得到网页源码* o# n% ~3 m: X2 Q% A0 o8 D
( o7 l" Q, h$ u; L+ wprint("内容:",response.text)
3 B# F* @8 I8 s$ a* Z" C1* r" t. s3 D+ _" \2 x6 d* |
response.content是response.text的二进制形式$ g' N+ A; k7 A) b. @0 E
/ A8 |: x; h* n# Z7 X4 n至此,一个简单的爬虫请求就算是完成了。
5 l M/ {( _$ ~% ~ v当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
: P+ P. P" ]+ z. yf、解析网址$ O3 D( Y1 f3 k9 Z' @" G
刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
6 ?, E8 y a: {( M& z! V4 L8 ABeautifulSoup:
$ l0 M; h0 f. C* l. Y( X首先导入需要的库文件:
1 j# u: D2 {% C# }- t' I+ M2 O7 L/ H5 z
from bs4 import BeautifulSoup
$ z) G P2 K0 N1' W, G$ g x4 e; \$ m; D, q
然后对上面请求得到的response进行解析:- }0 y% i9 @7 ?4 S! a
2 g: b' f4 D d; _" b6 ^html = respone.content.decode('utf-8'); g& Y0 O, d+ z; G
soup = BeautifulSoup(html, 'lxml')
- n: g5 [0 R. b1
" Z! x1 ~! ?' {, ^2
8 u8 v* v" ^' d, J; B以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
" y9 `. M3 d t1 X; A# G8 i# 获取head标签
1 c P! ^. O: x; C; U# n- P$ mprint('head标签内容', soup.head)
& X7 g0 |0 y1 _1 B i! O# 获取title标签
. @; m) w, f% _6 Dprint('head标签内容', soup.title)
" ^) W, F* y% Z: ~+ V# n# 获取body里面的img内容3 ?: q( [) e2 l% g- c3 O6 X0 {
# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
) R! Q, ?0 q6 o# Bprint(soup.body.a.img)
# B" e2 d0 `8 H+ k# 获取所有的img标签 使用find_all()搜索整个soup对象" }. W: K) X3 @/ h! {
print("获取所有的img标签", soup.find_all('img'))2 t4 q- J2 _$ {7 Q) v0 N1 @" Z% @
# 获取标签中的属性src地址
' h5 |0 O6 {- C2 w* g. r1 X& |- Fprint("获取标签中的属性src地址:", soup.img['src']) # 注意:英文点号都只能获取第一个值2 R, O' m$ u, `8 `! c- B+ X
' e$ M4 K' [6 _& V3 x; x# H7 s8 z# S3 @7 h0 y" f& R2 `% r
# 获取soup的name5 |& o& V. |3 b+ K" N9 N$ F
print("获取soup的name:",soup.name)% N5 O' p2 Y6 ^; ?! s9 b
# 获取a标签名
2 W0 Z, N! I0 x% T( W' F; C7 tprint("a标签名字:",soup.a.name)* c9 ?* X* Z, `; a' R3 D
tag = soup.a" X% q; x# ^; c8 D
print(tag)) }9 _. f& J5 _% s" a! F
# 修改操作 a标签改为b标签; ~3 u/ V" s: S* o" E, n0 c. m
tag.name = 'b' # 赋值后<a> </a>变为<b> </b>4 t6 H! R6 a+ g/ R) C' j
# 输出修改后的内容4 w) h; u* A5 s) Y6 G X* ~
print("输出修改后的内容:",tag)6 G# M/ f7 Y1 r
# 获取全部的属性 attrs. \% I) x* K& R* ]$ ?
print("tag对象的全部属性:",tag.attrs) # 只能得到当前标签的属性(不包含下属标签)0 @& g8 x2 p6 \& [
+ a$ @0 R1 P5 h% G# 获取属性的class的值 根据键取值0 c% Q+ ~3 M. o6 i K. J
print("获取属性的class的值:",tag["class"])
& `: ~8 n6 t8 x
4 u* R% h; \/ {( f8 O6 N0 P. N4 F
$ W7 U* [. n/ x' @: X5 b5 ^
' q) L$ s, q. W( W' e7 `+ V2 @: r j b6 w) p% A4 |0 |5 r; w' m( l: `
"""针对获取的标签属性可以进行增删改查"""
( S6 R6 H" P+ ]9 L% n# 修改
8 }3 e5 M( S/ t0 E% W# dtag["class"] = "Logo"8 N, B& Q M8 { B8 x5 ?" D
print("tag对象的全部属性:",tag.attrs)4 t* \. P- x0 q7 A4 r
# 输出属性0 e# u! b$ m+ s: L ~& f! m
print("获取属性的class的值:",tag["class"])
9 O: Y' ~! ? g5 C$ d# 新增 属性id 赋值logo
- X: s+ p ]& a+ ~3 v+ b8 p0 v6 Q1 @tag['id'] = 'logo'4 ]# N0 [, A" B4 v, ?1 O% J7 r5 U" |
print("tag对象的全部属性:",tag.attrs)0 t8 a5 q1 x% e! g( @5 J
# 删除属性3 p5 u x9 [) t
del tag['class'] V6 p# w; }1 D# N* }; v0 y
print("tag对象的全部属性:",tag.attrs)
" B- w [, h* v/ y* s i
( W' A7 m3 u5 U( A p* S2 J0 _+ S6 ]: F. f& v" S
- C: x e* J2 ~) _& Z
"""针对内容操作 (只针对标签,对属性无效)"""% U7 F1 Y3 r9 r2 H7 T1 M; C
# 获取title标签内容
' N, j8 ^; B$ q3 { Dtag = soup.title
1 b6 \) s: f* R$ |& y* X- K( {# 获取title字符串
1 j- e, }) W- g0 X, i* N$ sprint("tag对象所包含的字符串:", tag.string)1 x# I& E+ O+ ?' q9 G
print("类型:", type(tag.string))- W- Z& M7 s. U. K+ c
# 替换内容- Z0 y U) i6 s( V" W, d
tag.string.replace_with("你好")
v0 p7 ?9 D+ G5 p+ [9 u3 Pprint(tag.string)
- e& m) V. {% E. w2 |" c# <!-- 学科建设 -->
2 ]( P- W# V' y: ], p# 获取注释文本内容
: P; v. H% i* {0 Xmarkup = '<b><!-- 学科建设 --></c>'
- t" V" L: z+ M4 O* Msoup_comment = BeautifulSoup(markup, 'lxml')$ R* u8 ^7 k8 T
comment = soup_comment.b.string # 以markup第一个标签作为关键进行搜索/ c2 n) i# k0 `9 H( O0 Y/ n
print("获取注释文本内容:", comment)
) e, w7 F4 Y. o8 @2 N: N3 ^0 }# get_text()
- p0 K" l6 q6 vprint("title的全部节点:",soup.find_all("title"))/ K- E7 f/ e5 `% F7 e1 ]. \7 R
print("title的内容:",soup.title.get_text())' s' H% X$ |7 O, p' F: f. p
"""查找ul元素标签"""; r2 S7 x$ w/ q
# class是关键名,匹配时后面必须加下划线_
+ ]; W5 |9 q; _5 E+ T# tag = soup.find_all("ul", class_='menu') # 按照css类名完全匹配
" }% D' w6 P" U7 E: P1 K% j# print(tag)
- w0 i* x* B j. A$ H( s0 X& utag = soup.find_all("ul", id='menu') # 按照css类名完全匹配
4 l+ n3 N, ?% a- xprint(tag)" s8 k* A0 [/ T4 ?
# 查找名称为a元素的标签内容: W$ ` p7 c7 m8 M% E6 d/ b
taga = soup.find_all('a')0 o0 m' j# Y( v7 f. L
for tag in taga:0 o( g- n6 z C2 e
print("查找名称为a元素的标签内容:", tag.string)* t% K/ l: p r
# get 获取属性信息 获取整个页面的img标签图片和src属性值& O. Q, }( j$ E) ~3 p
tagings = soup.find_all('img')1 x/ k% x l% z; {' ^# k/ m+ s2 Y
print(tagings)3 B/ T& d. q7 Z" x6 y( l A" u
# 循环输出图片地址3 o% e) A* m, n5 B: a5 g; d, e
for imgsrc in tagings:) J7 D p3 ?) n
print(url+imgsrc.get('src'))
1 L* w: W* v2 q9 |3 O+ T) |+ e: W8 p) K1 w" ^% h1 U
""""属性只能做为参数,所有的操作只能针对标签"""9 U' t# ]' J9 u8 _' l3 W, r2 O
2 G4 g7 E; V2 W1 h3 v/ }4 y/ ^
etree方法:- w, q8 n8 T# Z( n6 I0 @
导入库文件:
& J1 R- F& h9 B+ A% l) g$ O
. p+ L$ s- n' u, s" f0 J8 T* I& kfrom lxml import etree$ D' q. V6 r# K( G
1
$ m6 u% g& C& f5 f解析得到的response对象;: O+ d' A! n; Y0 g! Q6 Y
z5 p8 ]5 j1 F" D
# 设置response的字符集8 X d9 b0 u0 E4 ?& o8 o
html = req.content.decode('utf-8')0 w- [7 m! y7 L) I7 W* M7 I: @
# 解析对象
; t. {0 q: a( shtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
4 d+ a3 g- h* e: s6 g
2 Q: n4 ^- P' ^: `. S- v常用的方法:
% P9 U6 k( A3 Z, f9 G9 [) v) F3 `: q8 \ o" ^9 |) I
0 d( n; h0 C1 _: l7 B* B; j8 \# 定位head节点(元素)
t" ?% A3 ^7 z j5 B' t) Bresult1 = html.xpath('head')9 j ]" F1 ?- ~. G1 @
print(result1)
' J$ {$ y: _$ B3 A# 定位title节点
$ `& b, Z% n/ O, c- {result2 = html.xpath('/html/head/title'), q" O, v' e0 J! F5 t C- H
print(result2)
# V$ b! Y! |/ l4 p" {4 f# 搜索节点 title节点5 }3 s6 Q# }+ S
result3 = html.xpath('//title')
; L: u" G8 B, c2 Y& bprint(result3)7 A8 G$ ^8 t n2 J2 A* E% Q8 W0 O8 a$ V
# 搜索title内容 text()得到文本信息
8 |# @. q/ I6 b4 U0 I7 p' \$ vresult4 = html.xpath("//title/text()")# ~: A- d; C2 T+ S; D4 a3 `6 C# H
print(result4) M: I4 i3 p' K- r5 U$ X+ B) x/ N
# 搜索div节点) w' s1 }/ Q- x# `: F
result5 = html.xpath('//div')
6 x! y/ v; F, Q4 L; f3 m% [print(result5)
' {) g. |. G p+ h3 B$ e# 搜索div节点 并用class属性定位
6 U" o) y5 J4 @. d4 C$ ^result6 = html.xpath('//div[@class="news"]')! \* H3 Q8 t9 n
print(result6)
; O- n; y) ?/ e5 c7 V8 b/ x# 搜索div节点 id属性定位
9 U2 X& a: y. K- D e& Z; @result7 = html.xpath('//div[@id="news"]'), Y0 n- z3 w: i/ b; S2 ]
print(result7)
6 O9 W5 L$ E7 ?. T* v# s) r1 R# 获取列表span信息
: q, W) ~% _' X: o4 w+ c# wtext = html.xpath('//div[@class="news"]/a/span/text()')$ _4 L2 d" i: K F4 P
print(text)2 W& N d, l( s; }7 Q
. T& W( }9 _5 d! h
g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
8 c# f4 d' C2 R9 q/ a" I1 r保存的方式有很多种:
" K7 [% L6 ?$ `( J1、保存至文件( X0 I) p6 ^" V. h% k
csv、json、text
* i: r$ h8 E, u: c2、保存至数据库3 h' C. }; F5 Z) @
MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库) 关于数据存储后面再做详细介绍
) u$ c5 u: i; j, h% t c
S5 S6 @ q, Q+ H. d* k2 T. p; _9 l$ [% p! J) i) \
————————————————( ^, s4 O" w) s$ |% N# E% H+ [
版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
' h0 v2 O2 D2 E. `( E' G# J/ D, f原文链接:https://blog.csdn.net/royallucky/article/details/105930473' @1 d7 h% ]2 s: i9 A4 u1 w( r, e
$ m9 W4 |- y# {# ~" O6 K7 d. b- X3 N1 ~
|
zan
|