- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563283 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174208
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
+ f0 e/ M& M7 {/ Z0 @
0 ^* {- B+ ]& c f
6 y# v% V3 {; j. p2 i手把手带你5分钟搞定爬虫(聚焦爬虫)
2 |6 L& E! n. Q, S" l
$ \! ~8 W0 O, q/ S爬虫的原理
]# m( H5 [. q0 }( U6 e+ c" v5 k; ~* N) s; {4 }$ W/ f
对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫2 }+ X: O$ H& `4 I( e2 D
把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味0 Y" p$ ^ a9 e, I
所以说爬虫分为三部曲:8 {; W/ P5 b% E
1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)0 n& |8 e; s$ w
2、去找到你喜欢的食物的位置(得到目标地址). y" ^3 P. M/ U/ Y [# h+ ]2 K
3、把食物搬回家去(解析网址,获取数据,存储数据); g/ V2 ] ]# K$ a2 @
它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬). K- X+ i. n' Q0 ?0 j c
a、导入需要的库 requests
, |1 b/ a. n8 @; E# i
: i- `0 O5 T& L- Q! Dimport requests
9 N8 ?/ G" C e9 Y" b" Q7 A) i1: g. w! A$ X# I7 r2 l: J% A. E
b、明确你要获取数据的网址(这里以百度网站为例)' [9 l7 f9 s4 p# x2 O3 ?
" e# R3 r" J' x- Q/ `url = 'http://www.baidu.com'' L' K1 d- X; x/ y; b" G
13 M6 s# m* H4 t
c、创建请求
% ~6 q9 g a! x$ X% ?6 Z; R; S( p# O
& Y' u$ U4 \. B5 Y9 qresponse = requests.get(url)
) [* R7 ]: V" W1, J! [0 j% W: ~+ P
d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
! a" Z( U8 j9 n& Y9 x) s5 Z2 }0 b9 q
print("状态码:",response.status_code)
) k$ ^/ _; b8 y5 @: |" i1 f1/ i% `0 F% N% I: _- S8 E
当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
2 w5 }; i7 L# `e、得到网页源码
6 F; ~. F+ _5 f! ]3 U4 ?" i. l: }" N6 V, u" }% T4 X. M V
print("内容:",response.text)7 g w5 i$ w/ G1 }+ _6 p! ]
1
: \, ?1 y# X) e k W" ]response.content是response.text的二进制形式- u, p3 q" T7 ~8 ~$ P
' z1 N0 |9 U4 Y6 L+ g3 c6 X至此,一个简单的爬虫请求就算是完成了。
5 K9 o( l% _- z) d当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据 `2 _, ~7 h: k( a
f、解析网址7 }! c# l+ w( G0 L+ o; N0 W
刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
$ |, _ C m: Q$ L; Z' Z7 vBeautifulSoup:! ]- {1 H/ o4 x* Z8 K* @6 z
首先导入需要的库文件:
6 ^7 ]( `0 V( R" K/ [3 Y2 q8 |* M; D; e _
from bs4 import BeautifulSoup
2 P( K9 y: v& _& J7 H9 M- U! r" e1
' ^, K6 S, @0 V然后对上面请求得到的response进行解析:
- W+ [6 c- n! D k- e+ T2 z& {* s
html = respone.content.decode('utf-8')
0 `4 ?' J7 ]$ \& j+ I" h3 ]* msoup = BeautifulSoup(html, 'lxml')8 t+ o# ]9 h( }/ h; O
1
/ f8 ^+ Y% G! q2
' C* Y% @3 H4 }: Q$ ~( T: l6 F" B1 b以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
: u+ M& [: ?8 M+ j& C6 w# 获取head标签
$ p( _8 J. ~: f5 ]/ o0 {print('head标签内容', soup.head)
n! d% Y! B) H9 Q( F+ ?) w# 获取title标签
5 s8 d! f2 d- Jprint('head标签内容', soup.title)
7 ^) R4 ~/ S) B- B- ?# 获取body里面的img内容+ h: m' W# k. Y3 F
# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
# S2 c; W# n* Y1 nprint(soup.body.a.img)
) r( y5 S; A- b2 E' X# 获取所有的img标签 使用find_all()搜索整个soup对象
: I7 G2 t, m7 h5 Z0 \8 `print("获取所有的img标签", soup.find_all('img'))- v) d2 e0 _& S7 a$ A
# 获取标签中的属性src地址6 F0 M$ Y8 i2 n# Z9 d
print("获取标签中的属性src地址:", soup.img['src']) # 注意:英文点号都只能获取第一个值! p8 i! k/ T- t3 d
/ ?; C' C6 n+ P9 d5 n. A8 a s7 \: b' m6 I% @, z8 J1 R K" N! ~
# 获取soup的name7 b" B$ s5 c2 Q! J9 b2 p9 \
print("获取soup的name:",soup.name)3 l2 |2 e: G' c5 X
# 获取a标签名
+ g! R. ?/ F5 v, J+ [, aprint("a标签名字:",soup.a.name)
, u& F1 ^4 {: K- f' y6 y$ Rtag = soup.a
8 n( Y" z* R+ I; }- Dprint(tag): Z# s8 J3 ]8 E* H) J7 Z
# 修改操作 a标签改为b标签0 ]* F! h( ~; s5 V4 p: F
tag.name = 'b' # 赋值后<a> </a>变为<b> </b>! }. V- Z8 h7 B* l! J
# 输出修改后的内容
% C, Y/ x @# G; xprint("输出修改后的内容:",tag)
$ l- x0 _4 W6 j+ v7 J# 获取全部的属性 attrs4 `: e' b1 m! U! Z# r7 ^
print("tag对象的全部属性:",tag.attrs) # 只能得到当前标签的属性(不包含下属标签): O7 y) C5 Y: c- f) l4 @
, D+ c6 V2 j# `
# 获取属性的class的值 根据键取值. Y. o: F( y& e, M U" j( i- m/ j; T+ {
print("获取属性的class的值:",tag["class"])8 U; y+ d& C$ `6 w3 j- B
+ [2 z8 S q' N% s; y
# o. g# @. w3 z; w" X. o5 g
# v. n2 ?$ `5 ? A' I& e: e, O, x$ o8 w7 C* D
"""针对获取的标签属性可以进行增删改查"""4 j4 A8 _4 J$ Z
# 修改
, d8 K B4 k( v) h0 L0 itag["class"] = "Logo"
, S8 T0 s1 P$ a, J# _8 @print("tag对象的全部属性:",tag.attrs)
9 C! }, k! E: [% X' _# 输出属性' @7 `# j7 w* ?( j% s+ P+ T
print("获取属性的class的值:",tag["class"])& ^) R" u5 d j) V+ s4 r
# 新增 属性id 赋值logo8 l" \. v% S8 c! H5 F, q
tag['id'] = 'logo'
/ H" c4 s- F2 S) o; gprint("tag对象的全部属性:",tag.attrs)
' ^ l4 X/ w7 v9 u' f# 删除属性
) b/ a2 B7 Y) [. fdel tag['class']
" k4 e0 W/ h$ R Uprint("tag对象的全部属性:",tag.attrs)7 |+ W9 ]- v0 P4 N/ o, r6 ?
, {& S8 n( D/ z0 L# X
8 w" a' E. r. o7 x
8 Z: u9 i9 b& m
"""针对内容操作 (只针对标签,对属性无效)"""
3 u, c! O) h9 j2 a' J# 获取title标签内容
8 I; n! i: ]8 B+ P ttag = soup.title- F/ M% z, g5 c" Y
# 获取title字符串: Y; s* S& \% n, B6 R
print("tag对象所包含的字符串:", tag.string)
3 m( R% @4 |6 P" j( V. R5 kprint("类型:", type(tag.string))
5 r: A ?: {( v/ B% [. f# 替换内容
: R" D( Z3 l' M# L! |1 W. r o' jtag.string.replace_with("你好")
/ a$ Z" s6 t4 cprint(tag.string)8 E9 P$ D. g. ~& }2 ?: Q4 R: Q
# <!-- 学科建设 -->4 N1 Y$ \- {/ C4 u, l- g
# 获取注释文本内容
, R1 S b# [' [markup = '<b><!-- 学科建设 --></c>'& {' e$ ^1 \7 A' T
soup_comment = BeautifulSoup(markup, 'lxml')
0 ?: U* D0 q7 r5 c9 ncomment = soup_comment.b.string # 以markup第一个标签作为关键进行搜索6 |3 j: m2 Y9 r$ M0 Q
print("获取注释文本内容:", comment)
9 t7 K2 U5 u2 R4 A/ X) q6 A# get_text()1 c* {+ h/ ]+ v, u& ]6 v
print("title的全部节点:",soup.find_all("title")) m3 W( m9 i& j% s! `
print("title的内容:",soup.title.get_text())3 {2 q% k. [" H4 r0 w
"""查找ul元素标签"""& }# c2 K5 Q5 b
# class是关键名,匹配时后面必须加下划线_
- P% W T+ M- p& G7 e# tag = soup.find_all("ul", class_='menu') # 按照css类名完全匹配
- m! d$ ?5 W) J/ R# print(tag)
& |0 a8 t0 O& ktag = soup.find_all("ul", id='menu') # 按照css类名完全匹配
# H3 v8 F: O3 j# w- l5 Hprint(tag)
1 P- n8 D( X" ~2 g# w1 j6 m# 查找名称为a元素的标签内容/ e4 c4 g1 b: [& w3 W4 e5 A( W
taga = soup.find_all('a')
, U, V; |9 B o4 F0 l: ufor tag in taga:" y/ A# \- [( o' z
print("查找名称为a元素的标签内容:", tag.string)) u# i) v5 P, i" d0 ?
# get 获取属性信息 获取整个页面的img标签图片和src属性值+ Y |& r7 h4 _) [0 B5 @$ e1 R
tagings = soup.find_all('img')- _+ K+ a) ~ w, ^0 G
print(tagings)
2 i- b; u+ Q9 G7 V% W n# 循环输出图片地址* B% |4 X& T! L3 w$ }1 H" i7 Q
for imgsrc in tagings:. Y p5 g$ h2 P' v! @
print(url+imgsrc.get('src'))( k. h. h9 A s
6 W4 p: J0 |& E8 r) d4 Z0 p
""""属性只能做为参数,所有的操作只能针对标签"""
7 h( V0 M( Z p `1 [( ~: |8 r/ P
5 ~ U% U% r- ? p* Setree方法:
+ k1 `$ Z$ \3 D# \# T- k$ J导入库文件:
# Q) v8 O# F( x0 ~
) M: G8 f: u4 Cfrom lxml import etree
! \2 v- Z9 f1 q. t/ z1
k2 @( k: j3 M- l! s( G4 I解析得到的response对象;
5 m1 \% ^# g# @9 G- S: X; _; e, D6 z- J B! X
# 设置response的字符集8 T2 j# M- O7 L, Z, Y
html = req.content.decode('utf-8')6 `" C* O% u* K+ \. r1 b
# 解析对象
, z! |% m- p. U; thtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))7 d4 \& r* h. l+ Z# [. V3 ^
! P ]& a d1 I常用的方法:
3 A! o1 g& ]8 b$ A$ X9 K- P% i
; ]) w6 V5 ]/ |* Z% z# j
) u/ k1 k( p9 H" I! g: ?# 定位head节点(元素)* N! p0 L0 y5 u/ G; E
result1 = html.xpath('head')
& Q3 `! k4 S v* Qprint(result1)# w5 s5 _6 b* ?" s# T/ N. s
# 定位title节点
. {4 P; I4 g+ u1 K3 {+ c& Zresult2 = html.xpath('/html/head/title')
- ^5 F0 u' j" u4 m- ^0 n* B/ Y8 qprint(result2)
7 H) s1 k8 u; d# 搜索节点 title节点0 E; m' A$ o# _7 k" j
result3 = html.xpath('//title')" s. O. D. j) N4 I) l- b3 j- Z A, [
print(result3)
6 ~0 ?6 o4 K& K7 ^# 搜索title内容 text()得到文本信息
" E& v% H) k4 a! Q: Mresult4 = html.xpath("//title/text()")0 y+ C3 @. N% I+ R2 C1 G
print(result4)
$ V+ b4 G0 ]7 {3 q# 搜索div节点
4 N% g+ X- a/ K- ~$ u1 k2 j( Aresult5 = html.xpath('//div')
9 y% A7 m7 p6 d3 Iprint(result5)
* D% e5 u1 p: W7 L2 b& {+ P# 搜索div节点 并用class属性定位
: L5 c1 O' [* f& L) uresult6 = html.xpath('//div[@class="news"]')6 c7 e) Z; ?! q- ?' A1 l5 q
print(result6)* [+ z3 R* ]. K/ M9 R: Z+ F. ]" x
# 搜索div节点 id属性定位0 o, d: ?6 G1 r; J& F7 J' O
result7 = html.xpath('//div[@id="news"]')0 a6 D A/ B+ y/ O
print(result7)# g! i% \; ^- w3 ]0 c: x
# 获取列表span信息+ m. B; G2 c! x+ x" T. }
text = html.xpath('//div[@class="news"]/a/span/text()')5 q5 {, l5 ~$ k# o5 R8 e
print(text)
( J. @; X S7 E* r; ?1 [4 I+ @' G1 K$ o1 i% s/ f
g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
9 m! e. J1 J, ^0 R0 Z6 Y, ~2 ~保存的方式有很多种:
$ C6 h- d4 H/ J# T6 d1、保存至文件
$ t" r* y: e9 ]" \/ k) ucsv、json、text
8 X# W7 i9 D& M! S% I" n7 n0 e2、保存至数据库) Y7 ]" A. _, [$ j
MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库) 关于数据存储后面再做详细介绍
# g- n, @( J+ i7 ^! O
% [; Y4 Y* |( `3 ^9 o( E
* n' f) [& D8 w————————————————7 P1 ?. R5 c+ _" p7 v
版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。. a/ @. L7 ^2 J7 O( L e
原文链接:https://blog.csdn.net/royallucky/article/details/105930473
7 d" S3 ]6 @$ a" e O7 R5 W8 X$ V3 }. _
" Q+ t+ Q) x0 a9 {0 c% A0 }9 A! {6 \. @ |
zan
|