- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563288 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174209
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
9 g$ p# D- L% ]$ _. ~
. G R3 u9 y& F3 p / }: q& C- y$ W' [$ u
手把手带你5分钟搞定爬虫(聚焦爬虫)
9 A+ |* }. @: V: j
; S& f. W( e4 \7 K# \爬虫的原理
& r! r; L. X! x$ Y5 B7 M( I0 O/ d; u+ k0 Z" t5 n
对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
* ^5 a# k" w/ Y把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味
) A& W( t2 v( b/ c! R! S5 k所以说爬虫分为三部曲:
I6 b7 R/ J3 f1 ]8 y; n& \4 W1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)! F6 C) a) b0 W' O3 B+ r; R
2、去找到你喜欢的食物的位置(得到目标地址)
. J& ~( [! M0 ^. C9 o _3、把食物搬回家去(解析网址,获取数据,存储数据)
7 x- M, [' X6 g, W: y; e. N2 J+ e. [6 S它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)2 t; ~( F; X3 D, v- Z
a、导入需要的库 requests
5 l& O; J0 L& n1 G' Y; A% B' n3 Y+ O6 f! ]7 l2 k6 h2 o
import requests$ i2 H: G* i' \$ S) A& F' V
1
% Q$ _1 c! s& d4 Y: pb、明确你要获取数据的网址(这里以百度网站为例)
4 o. D5 {# c% z" Z: w7 }/ H4 [4 C
7 ^1 [: d3 r$ b! r! O durl = 'http://www.baidu.com') m/ r6 h, {. h8 A% n
1 e' Y- x0 I) }& p/ k3 a, U8 A
c、创建请求
; I5 r) z! x- e$ A# x
& ^5 D; s6 o* w5 Jresponse = requests.get(url)
l& Z4 [! B' G/ f& B4 W- ^* z% n$ I& {* `1% R. F6 B i' W
d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
* J7 I: |" _& z6 }8 N. G1 X- {: z4 I4 I* O; g; `% Z' {0 [6 h" h
print("状态码:",response.status_code)
/ z- e F5 [3 Q, |5 T5 ?1
v" s R2 Q; Q. G4 g% A/ v3 g当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
$ K6 T8 G5 P/ D) se、得到网页源码
+ I4 C! \# @1 s# p) j
' ]5 d5 j, [4 ?5 J9 x& ?print("内容:",response.text)$ }) g$ a. r/ v0 G g. T& A. Y. M. I
1
8 o( w5 H! e! K# {response.content是response.text的二进制形式1 I5 v3 n2 g ?: F3 S6 {% N
, i3 C5 N2 L. K( L2 L' _
至此,一个简单的爬虫请求就算是完成了。! a6 U8 T3 S6 q7 f5 {
当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
5 Y2 o; B, v" N0 a. tf、解析网址
. J. a3 w; y8 f; _% n刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)' ~ m$ F' ^- L9 h+ A+ b
BeautifulSoup:
8 q. z8 L1 f8 |" I+ I首先导入需要的库文件:/ i( S0 \! Y; ~7 q2 l
, A& F. m2 C9 f' ?" V5 z5 E0 }from bs4 import BeautifulSoup
( ?9 ~$ Z9 Q& f' |6 Z+ x/ {1
3 `9 a2 O5 {3 X+ T' e/ _$ @; h4 j; P然后对上面请求得到的response进行解析:
! s. O$ e8 F6 r% x/ \
; n0 t$ J2 k2 K% d- r0 R+ dhtml = respone.content.decode('utf-8')8 i" V' e7 [# Q
soup = BeautifulSoup(html, 'lxml')
8 S0 I0 ^' i4 X* b0 C- v1% ^+ [8 K. c! d9 J
29 _) v! H( D: V- ?& k3 Y; p: w
以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
' w1 A$ j# e+ K( g2 f7 F- C# 获取head标签
& {) W, ?4 k" m+ _6 t9 ?# Bprint('head标签内容', soup.head)' ^6 b, c/ c( }0 ]9 ?) h( I6 O
# 获取title标签
& n9 z, z% d: E5 b5 C- U Lprint('head标签内容', soup.title)/ M4 c/ W: x5 u/ p
# 获取body里面的img内容
3 I" j; |4 X3 c' B9 P7 v) l8 n# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
4 c5 Y" @- D, Z% @print(soup.body.a.img) / r. E/ L7 {$ V: D! n
# 获取所有的img标签 使用find_all()搜索整个soup对象
% c' ~6 ]0 c! h$ U. F1 gprint("获取所有的img标签", soup.find_all('img'))
+ j2 I% `% K) _; A( y4 |. ]" C# 获取标签中的属性src地址# E9 @- f# R% r; G( {, \2 ^* k
print("获取标签中的属性src地址:", soup.img['src']) # 注意:英文点号都只能获取第一个值
5 J7 X% P& q+ y- P3 L
& J9 \0 O! M3 m: \& I2 t
2 T7 S; v3 \' g+ ~- N# 获取soup的name
# a8 s/ X: E" V5 v7 \! dprint("获取soup的name:",soup.name)* I+ {$ l- C' v
# 获取a标签名
' N+ s% n+ k2 C4 C0 U! Hprint("a标签名字:",soup.a.name)5 X+ P7 P0 ^' p& t8 {, n
tag = soup.a8 c4 X! f2 I! m' t2 T |# ]+ c, Z
print(tag)0 a5 k5 h( g5 d. N o0 U1 A& Z
# 修改操作 a标签改为b标签
) B! s$ n8 G3 Z E0 @# k3 qtag.name = 'b' # 赋值后<a> </a>变为<b> </b>
% q. q" Q h% G7 p. @4 U# 输出修改后的内容
) W& d O% V5 F( l+ L# S' Kprint("输出修改后的内容:",tag)5 w. I' T5 r' E
# 获取全部的属性 attrs
7 l9 h' C X! W# w2 T& ?print("tag对象的全部属性:",tag.attrs) # 只能得到当前标签的属性(不包含下属标签)
) q7 i1 y( S; {+ S0 g' G4 z: W9 o E6 A; v' e& [# i
# 获取属性的class的值 根据键取值
* G4 O: D6 D: {! G+ t1 tprint("获取属性的class的值:",tag["class"])3 @% R# f! F. a* Z8 F# I+ e
R8 {& M0 ]* z' Y$ [4 c! ^! j" }3 I5 U: j% f
3 W: s1 n8 G- Z2 J* N* f; X+ s
"""针对获取的标签属性可以进行增删改查"""! Z* s( s+ b4 Y4 ^; F5 g
# 修改
4 ]( ?+ s# W. f: Z: D& Gtag["class"] = "Logo"
( v5 s: F/ \; g/ p0 o, s$ e8 ~print("tag对象的全部属性:",tag.attrs)
0 G; t4 S, h. {4 O# \- E# 输出属性
) c0 s8 G" z2 g4 _; ^print("获取属性的class的值:",tag["class"])
8 R( G1 m9 r# x- R# 新增 属性id 赋值logo$ o; L: K, ?$ w; E; Q( ~* W+ B
tag['id'] = 'logo'. s4 U# k0 X) L+ o$ o: |' S3 Q
print("tag对象的全部属性:",tag.attrs)
7 `! V$ ?% p# v9 G- l; T$ E) C* v# 删除属性* \4 L9 t+ S7 J8 t. M" S: o n
del tag['class']
5 }. P' [- b) }' L0 ?& n9 L) W8 e0 ~print("tag对象的全部属性:",tag.attrs)) c0 E# k3 ?) ~6 L/ Z
& C# }. |$ X( B" W8 j8 y( U& d- o" ~ \: }
2 K1 w: |5 P2 F# M4 H5 T2 }
"""针对内容操作 (只针对标签,对属性无效)""", i# m7 r* h5 e4 j/ T
# 获取title标签内容
2 A. g& ], G1 Z+ rtag = soup.title0 |; N5 c9 B. h5 E
# 获取title字符串
# R) b" Q, O2 K) Bprint("tag对象所包含的字符串:", tag.string)
+ R3 `8 ?' a: U- ]( X7 Dprint("类型:", type(tag.string))2 Q" |" P) U6 c" V1 }) Y) t
# 替换内容
# ^' L* @! T8 K. C' `' o( V& Ftag.string.replace_with("你好")
/ q @* M7 w, ]9 `# aprint(tag.string)' M- o8 ^0 b' e
# <!-- 学科建设 -->
! g& J+ M0 B, Y5 \6 R; V; F/ w# 获取注释文本内容
# |1 S* j4 r7 G, pmarkup = '<b><!-- 学科建设 --></c>'
; F% l4 y4 t) o; H- ?; y0 r, @soup_comment = BeautifulSoup(markup, 'lxml')* ~' m8 s2 L. v0 {" r8 v$ E# \
comment = soup_comment.b.string # 以markup第一个标签作为关键进行搜索1 {6 ?) z) i* ^' D
print("获取注释文本内容:", comment)$ Y' I6 s; }8 N9 h$ a% ^( ^6 }
# get_text()
6 J# D7 P5 U( @$ F% n" C$ Lprint("title的全部节点:",soup.find_all("title"))
. B+ t8 n5 y' X! X4 r' zprint("title的内容:",soup.title.get_text())
5 C6 @( c& G$ y/ l w' B1 h"""查找ul元素标签""") J; a X: t, i2 w
# class是关键名,匹配时后面必须加下划线_; S) r- y5 v: f+ L
# tag = soup.find_all("ul", class_='menu') # 按照css类名完全匹配 N, k, ]9 ~8 E5 [7 }' b7 [
# print(tag)
$ e6 @2 ^% h1 j) ]1 _tag = soup.find_all("ul", id='menu') # 按照css类名完全匹配: |" s* D* C, K9 m. S* z
print(tag)1 ~- k1 d* u% g! Z- N* X+ f% H" P
# 查找名称为a元素的标签内容
' i8 e' X: P- ?& s5 btaga = soup.find_all('a')/ h1 m2 h# }' g) \0 f1 g0 |+ c
for tag in taga:3 \; j0 z( u% E7 E! i1 _3 |6 @
print("查找名称为a元素的标签内容:", tag.string)+ E- J3 l' D3 v, a
# get 获取属性信息 获取整个页面的img标签图片和src属性值
' E+ M0 D- _2 R, l" W, ltagings = soup.find_all('img')3 @( _/ s$ D& N; @/ v: N; W
print(tagings)# ^& u9 }+ u4 X: ?2 U0 [
# 循环输出图片地址1 s$ _; g$ ^) ^! y
for imgsrc in tagings:
* ?3 h6 n) M; D; q, p print(url+imgsrc.get('src'))
4 v' x6 k* t& v( m2 N9 V; f m, |1 h5 k' w6 D% j
""""属性只能做为参数,所有的操作只能针对标签"""
: v& S7 c6 i8 A! @( b4 E6 w& O/ i9 [& p' e6 q* X5 K
etree方法:7 W: o1 b; h5 O2 C1 A
导入库文件:
# M. e6 v7 b7 a2 l) s
/ F0 W$ i! l& U* W0 C e, Ofrom lxml import etree( u8 a/ j8 ]; J" K R
1
6 l+ L" A0 m P' t* S5 b* J1 N! y解析得到的response对象;* U! Q2 @: n8 o5 Q+ K$ J5 ]
2 @, q$ O. ]: @7 x1 B$ R
# 设置response的字符集
* J. @4 K# q% Uhtml = req.content.decode('utf-8')
, n9 e4 ^6 R# R2 {4 ]# e# 解析对象
" L) i4 G! D& p# _html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
1 x$ x8 V4 q6 P! h/ I- V& r
8 c3 s4 [6 K: U常用的方法:
8 I L1 v7 H5 p; R, u" P3 `3 u% v" A( e
' f$ u( l9 y% F
# 定位head节点(元素), Z4 z; j0 x+ q% Q$ l6 n
result1 = html.xpath('head')6 X: }: N: v7 Q: H( a3 i
print(result1)
5 u8 [7 H/ `0 ?( s" p; a; ^# 定位title节点5 d( X* ?+ h( K/ O' }2 v1 z8 T! u
result2 = html.xpath('/html/head/title')( q* h! ?, v; D& [
print(result2)
9 U2 ^* ?. P( J8 R$ W8 {# 搜索节点 title节点4 h! i( {1 E8 Q" U
result3 = html.xpath('//title')) ?" {. t1 _. l1 Z) C- L4 O: k& d
print(result3)
, |# T+ ^/ n" g( B+ m) ~# 搜索title内容 text()得到文本信息$ C. @9 g+ S$ W3 s, r- X! W. z
result4 = html.xpath("//title/text()")- G O F: R) e- W6 q8 l: I
print(result4)
- J f3 b+ b# s* T u5 Z6 C! I# 搜索div节点
: g' \) K1 a3 t v f* z4 b" {+ Mresult5 = html.xpath('//div')) q5 S8 Q+ ^ |4 m: d0 Z4 r
print(result5)4 v) E5 ^" t- T% a R, |* i
# 搜索div节点 并用class属性定位% W) w5 i8 a8 e
result6 = html.xpath('//div[@class="news"]')( O6 | m b2 J+ x# E1 r _
print(result6)
- s0 ^" O- d# M) r; c# 搜索div节点 id属性定位* A/ {* O8 _* ?) S8 A
result7 = html.xpath('//div[@id="news"]'). ~# t: Q: |& W m3 q
print(result7)
3 R8 s, M0 F' y q( y" n# 获取列表span信息& n* h3 w; m4 ^. M3 ~+ e' P
text = html.xpath('//div[@class="news"]/a/span/text()')
- D$ p9 T% ~$ n# i j8 tprint(text)
, |+ }! A. a3 K: Q$ s5 {! k
& r! H4 c- E% t9 [ f0 S6 Fg、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存" r- A1 s/ G. N
保存的方式有很多种:) b& |& @" k R$ P7 F/ u! @$ k
1、保存至文件
! ]2 P% J }2 |8 Y. vcsv、json、text
4 Q- A( _; I3 W$ t: K' y9 q" C) r2、保存至数据库# @, y; R4 w' N, W/ U% B* R% z3 S
MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库) 关于数据存储后面再做详细介绍5 q% H* `# L2 f
/ _: p; o9 c+ ? r
# P4 ^# `) `) ^. V S1 j
————————————————4 G0 e- i: Q# w" [5 p3 D, x& G9 ?
版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
8 Q- k( r. J( }9 F( P( ]原文链接:https://blog.csdn.net/royallucky/article/details/105930473' D9 f3 L) X, v; P; o. F
, `- F5 X2 j7 F0 ^5 { n( f5 t8 Q- s& z
|
zan
|