- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 565783 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174958
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
& Z6 Q* g' F9 K
, U# i# q: C7 y
9 f& \" o: t9 `4 D9 u. @
手把手带你5分钟搞定爬虫(聚焦爬虫)
2 _0 j( M7 u3 Q- q; F/ v
0 A# g) V7 i& X" f8 T4 C- V9 I4 a爬虫的原理
8 M+ `% g7 D( E! @7 r8 d, k0 c K1 X; L2 @ X
对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
' e3 |4 ?3 T) x; k把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味0 R& r! t5 o' \ I" b$ ~; _* z
所以说爬虫分为三部曲:
% e# j/ |" n$ ~3 x2 F5 A* Y6 n1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)
: x8 L0 U2 c$ `2 _2、去找到你喜欢的食物的位置(得到目标地址)
, c% U2 o, B6 r/ X8 b' s& t9 A H3、把食物搬回家去(解析网址,获取数据,存储数据)
; n8 Y( u8 e: r) _它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)% S% F4 H6 ]; O5 d) P2 a4 o
a、导入需要的库 requests" q) a, Y; y7 x+ p" X! a
4 I" d* X0 {8 n! ~! R/ A7 n6 h: F) mimport requests; F6 R) F1 A* g3 c; k1 X
1; ]5 b) N, [) V/ o) u
b、明确你要获取数据的网址(这里以百度网站为例)
. h& N9 J8 S$ }9 p3 ~ c
/ N `' \3 x; ^- Furl = 'http://www.baidu.com'. G/ q0 I* T* _& b6 A; }8 N
1
5 \, Y4 m# |9 D& |1 Tc、创建请求
+ Y+ k# D3 _9 x! M6 J& S- P4 Y. r: ^9 y( x; S$ M, a& P' T( f
response = requests.get(url)
5 u0 `; h& b! z& a# N1
' s3 H, H( z( q/ ?* }* H9 Zd、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
f3 f2 U8 W0 y$ j2 m* U g( }9 U+ d" S- c$ \4 k5 S
print("状态码:",response.status_code)/ ?$ J7 f$ D( k4 R
1/ {4 K) ~; \- x
当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
) c) P- V# } g8 k( ue、得到网页源码
/ c* {: s9 x5 t0 c
) a3 V" O& A" ?' P; M7 jprint("内容:",response.text)( g) N. S* O5 |, o; [) E
12 z% p/ _( K% ?7 z! C2 M
response.content是response.text的二进制形式: F& b- b" P; |+ D8 R* w; E8 `
- a. ~8 d; p, }: G至此,一个简单的爬虫请求就算是完成了。
# K& f2 m& W; c0 z( F当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
( W' X7 [5 U- d% _. Hf、解析网址( @ a7 k! `) s' j& c
刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)/ x8 Z. M0 ^& @! I- h
BeautifulSoup:4 U9 }! ]& S- I- s! P/ {
首先导入需要的库文件:& O; q0 T/ ?7 s1 B
9 H* R- s" E, u) f" y" a* y3 Y
from bs4 import BeautifulSoup: ^& J7 m& }# x: ^4 i& I+ s" x; z
1
+ m/ @0 I( y) M4 X8 b* O6 M然后对上面请求得到的response进行解析:
5 Z P: l! w' @. S9 u! n
! u: c/ s" R/ N: C; s3 j+ ^% ~html = respone.content.decode('utf-8'); X8 O* x- @# j6 _
soup = BeautifulSoup(html, 'lxml')
# J. ]3 {: N4 Q4 z9 i% f14 k" v4 B L. |) n0 R* P
2
+ {# W5 `& \. O. ?以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
1 I% j# l& V% g0 J7 T* M# 获取head标签. [) L1 y' }! I4 d% G
print('head标签内容', soup.head)+ j2 S# G, f% c; y, G2 ~. m
# 获取title标签
+ u3 z( [/ d7 Wprint('head标签内容', soup.title)
( B0 ^" O6 C' B0 m# 获取body里面的img内容( |* f9 ]0 _- A" h. G+ g/ X
# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)0 V1 d8 t1 O8 p- J- W7 [: u
print(soup.body.a.img) 7 p* J+ H B8 Y) i. E X3 m8 q( \
# 获取所有的img标签 使用find_all()搜索整个soup对象: m5 s N# A$ y! j/ _
print("获取所有的img标签", soup.find_all('img'))9 f2 _: k7 i: F4 j
# 获取标签中的属性src地址; K ?$ F8 [! C4 n4 C
print("获取标签中的属性src地址:", soup.img['src']) # 注意:英文点号都只能获取第一个值
' j# j) ?# x* u7 I; @
- _& W4 A$ F k( a0 O3 s5 u7 E
4 P. F# Q: J- b! ^2 N9 ~; c/ ^# 获取soup的name L y( ]" m# i& Y% ?4 t) X
print("获取soup的name:",soup.name)
- L1 A) E( B& N* U- p. Q' T/ q |/ t# 获取a标签名5 A! p. V. e! }- T8 ]
print("a标签名字:",soup.a.name)4 {& Q8 J# S/ I) k* U( u& W
tag = soup.a& e+ \- Q+ p# t! a5 }2 C
print(tag)2 O" R1 M3 P/ x6 Y! S
# 修改操作 a标签改为b标签 i' D4 ?! t& y& u! l2 A* g
tag.name = 'b' # 赋值后<a> </a>变为<b> </b>
5 N- f! M2 ?$ p" |/ K# 输出修改后的内容
; J, x5 j7 r6 J4 P5 g9 G, e/ Iprint("输出修改后的内容:",tag)
' B X: V( U9 c$ W. B& ]% f" J# 获取全部的属性 attrs
6 g2 I& {# i; Z4 E+ Eprint("tag对象的全部属性:",tag.attrs) # 只能得到当前标签的属性(不包含下属标签). ^. J R- n: m1 n; j
' w$ N: F2 M) u# J% N% ^, K5 b7 l# 获取属性的class的值 根据键取值
$ u( B k5 c$ \/ }8 j* _% O2 ^print("获取属性的class的值:",tag["class"])
! ~! _, Q; q" _# S& q! m3 ]; ?& \) K5 R9 I& _
& X' e8 `& t6 n/ h1 u1 u7 f' y
& {6 { c3 B4 D7 j% p; |. O. [3 s& @4 M2 ]+ c: p$ q
"""针对获取的标签属性可以进行增删改查"""
7 v7 I; f2 \ c, r( V! p# 修改% u9 c2 u( Q1 w- G
tag["class"] = "Logo"+ Y2 d* \+ _( n: E
print("tag对象的全部属性:",tag.attrs)5 V0 o9 ]5 }+ l! f2 ]5 {, b2 o
# 输出属性* p5 X j R% w# Z- {
print("获取属性的class的值:",tag["class"])% R% E# V, k/ S* v! [
# 新增 属性id 赋值logo! v/ @7 ]/ L3 q4 D1 v6 n
tag['id'] = 'logo'
; \+ [# X# W" Aprint("tag对象的全部属性:",tag.attrs)
: n" J+ ~3 k5 C: ~; p( J# 删除属性
0 _( E( v/ f1 ~. U! r" o! ddel tag['class']
7 g+ \7 @) s7 ^4 {8 tprint("tag对象的全部属性:",tag.attrs)) r8 Q9 Y' w2 e/ g! W) u( d
$ g J+ U1 f/ q, a1 ?! D
% }9 G8 y0 n8 P: u' ~3 ^' T- H$ m. C
' k& s' n' |+ P1 b! j"""针对内容操作 (只针对标签,对属性无效)"""
% H+ ]: i( I+ J* Y% z# 获取title标签内容
! {% c& i. D0 X7 {" G6 ?tag = soup.title% d; ?$ W3 z! _" s
# 获取title字符串3 H% K& S W, \' C( k" i
print("tag对象所包含的字符串:", tag.string)- S( I1 Q7 E% N/ @! V/ m
print("类型:", type(tag.string))
, G. m/ F. }8 @8 v3 F# 替换内容1 ]1 c) d7 t* |0 ?/ K7 x
tag.string.replace_with("你好")2 E" g0 O" Y5 S% Y0 O
print(tag.string)6 a7 Q/ r8 i n
# <!-- 学科建设 -->
% R3 r4 w$ q( v8 l# 获取注释文本内容: q$ |: p/ S* s+ W; @- r# [( L& m- g
markup = '<b><!-- 学科建设 --></c>'
3 m: f. y% }" {: w# K1 lsoup_comment = BeautifulSoup(markup, 'lxml')
7 s7 L; K% L- L& f3 kcomment = soup_comment.b.string # 以markup第一个标签作为关键进行搜索
]$ ~! @- o! T8 g! y) Jprint("获取注释文本内容:", comment)
/ ?, k. J9 H+ l! }7 I# get_text()
. a# S' W* ? S4 b, wprint("title的全部节点:",soup.find_all("title"))( ]& ^, n r& F2 t5 w1 J
print("title的内容:",soup.title.get_text())
' ?0 Y& Z( l& c; c V$ Z6 r"""查找ul元素标签"""9 k: c; w+ p! ?/ K% O
# class是关键名,匹配时后面必须加下划线_
7 P$ y5 ]5 C+ V" h# tag = soup.find_all("ul", class_='menu') # 按照css类名完全匹配
0 F; X# _" p5 o* E, j4 `# print(tag)
9 h/ h* @" E' w/ `+ Vtag = soup.find_all("ul", id='menu') # 按照css类名完全匹配
) I: f6 X! X( U/ F7 z5 Fprint(tag)
: _5 X2 E) P# }5 B0 n' E# 查找名称为a元素的标签内容
% J) L) K6 ]$ [% u. C. r: ltaga = soup.find_all('a')) o- [- [; d/ S5 l S& y* R
for tag in taga:8 v, D4 M* p" U. n, z6 f8 ]
print("查找名称为a元素的标签内容:", tag.string)* \: X! e' S+ J+ l! O) Q7 c
# get 获取属性信息 获取整个页面的img标签图片和src属性值
9 l2 @2 `. J% _% ?3 [3 |0 s1 \tagings = soup.find_all('img')
% d* {$ f: _1 P3 N0 x- q& @. }print(tagings)$ C6 X; d3 z8 [( H! |
# 循环输出图片地址
8 c7 q, A" | vfor imgsrc in tagings:
! _: b0 n7 g# F print(url+imgsrc.get('src'))
2 W2 H4 n5 d1 C; Y, K: A0 R. h6 C, n* P# \
""""属性只能做为参数,所有的操作只能针对标签"""
: e* t3 h. z2 R- f$ v! l) E! d; X4 }( n' Q% u: F8 ^
etree方法:
" ^/ q9 ^! J) R9 i9 R3 _导入库文件:; y% ]7 ~ u+ }4 Z; ^! D0 }
9 J8 X7 z4 d/ }' M5 y ~
from lxml import etree
" ^8 _0 }# f, T/ ]1/ F: S, x N0 z; [: E% h
解析得到的response对象;
# K. D% I$ j# w l7 w$ t5 @4 e/ X I" e
# 设置response的字符集
8 a* `: F* | U2 ]( o& Dhtml = req.content.decode('utf-8')7 F- q& E# J# {3 z* o
# 解析对象
X3 L5 X7 @' ~9 Shtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
7 P( j0 u" b7 h( w# L4 W# `( h8 I8 X4 i% S+ o, x D1 A8 i3 R' p5 P' U( c
常用的方法:' n4 L, U4 c4 S4 Y+ u1 H
* X( [) D" q, l5 s' H* @; K5 F3 F
, V1 \4 A$ x% h3 w/ ?, z
# 定位head节点(元素)- ^* H. N; G" L& E3 r! z
result1 = html.xpath('head')
, {0 ^, W# [; W- Iprint(result1)
$ F, j" _. D) f8 k1 Q" A# 定位title节点& ~( C( d% V, ?9 S1 N
result2 = html.xpath('/html/head/title')
' \1 w% F% {6 t) j5 Q# Z# Hprint(result2)3 b$ Q% p9 a! [7 H* x
# 搜索节点 title节点; q! I5 |- T* ]2 p- w* r
result3 = html.xpath('//title')5 g; O3 k6 n7 w3 h$ Q% N9 J' n7 l
print(result3)5 O$ J0 y; w; d- B# Q
# 搜索title内容 text()得到文本信息9 G& R L4 W9 W1 J
result4 = html.xpath("//title/text()")" Y# C7 y9 D0 s- J5 F
print(result4)6 f' H7 P2 A/ ~9 |9 a
# 搜索div节点% a& q1 {# A: g5 F; y3 K
result5 = html.xpath('//div')
3 m& N9 h4 s" A+ d" bprint(result5)
5 o8 } _) b- E6 }; p, Z9 \% ]# 搜索div节点 并用class属性定位
3 u$ C; L$ j# C3 t Wresult6 = html.xpath('//div[@class="news"]')+ s9 N7 ~. F* W! U7 j
print(result6)
+ g) \9 ? d6 g% Y# 搜索div节点 id属性定位
' }) A% b' \% F, B2 Eresult7 = html.xpath('//div[@id="news"]')
) N5 ]$ \% q8 H1 b9 y; Lprint(result7)
9 j! q/ T1 P% V% i# 获取列表span信息- J) g, M) F3 ?% {: `, d( D
text = html.xpath('//div[@class="news"]/a/span/text()')/ e/ @6 w0 d) B0 N; H T2 v
print(text)6 `& V8 g4 q: K+ W
. ?2 h) d/ ^% K7 @: b0 H2 Q; _g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存$ s; x6 E8 S6 W# l( E5 }
保存的方式有很多种:3 l3 Z5 C% X! {5 R' d2 O- U
1、保存至文件
- q8 l; C2 M7 _1 g4 ]5 }csv、json、text) k! h& p" E) F6 Y' {* I w
2、保存至数据库2 q; ]6 c7 F4 G7 Q
MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库) 关于数据存储后面再做详细介绍
& Z5 J8 a0 R0 ]# `6 H
/ U2 R+ P' a8 r5 w/ q+ Y2 \9 C9 w$ G. E& j# B$ z3 Z
————————————————
: ^5 a3 @- M) T版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。9 U; {6 W& _- b2 |; B- V
原文链接:https://blog.csdn.net/royallucky/article/details/1059304738 F! J* q6 h- A( y/ e) `: c
! z) H3 D: `5 ]# @9 ~+ _
, w" w4 y- `5 X( o4 ^* s |
zan
|