- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 564698 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174632
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
/ E) B- u3 \' z6 k+ ^
+ k& q1 S2 e; K
' }: p* e0 B7 W- b% {
手把手带你5分钟搞定爬虫(聚焦爬虫)
1 o" |; J, b- ^+ Z
3 i, u" F- O1 p* w# I Q9 q' ^& |. H爬虫的原理
" j! C* m" s* a* T5 [& t X% _, f5 f. e7 k) D: l
对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫$ ^2 C! U# T! W! j7 r
把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味1 u- y' L& ?" l. y; ^7 l N& N
所以说爬虫分为三部曲:) y J. I% O8 r/ k: j
1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)
. Q% J& S2 C( ?# h' @2、去找到你喜欢的食物的位置(得到目标地址)! J' a; z! H8 `; ~5 `6 b/ W! X
3、把食物搬回家去(解析网址,获取数据,存储数据)
/ o' B3 [( T$ r6 |8 b' G8 S9 }它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
7 P; b% F3 W- R& S6 z4 W% I$ |a、导入需要的库 requests
0 v: u6 j5 j$ i ?3 j% D/ N. O/ z0 ^* B. G5 w6 q7 H% c
import requests* B1 f1 l. l' H: L
1- R" |2 g* d7 E& Z' D6 o
b、明确你要获取数据的网址(这里以百度网站为例)+ B0 Y! y- g6 d8 m8 i5 _
1 N$ B0 F0 ]. b1 T$ n: u4 U9 b
url = 'http://www.baidu.com' a3 m; s" z2 ? X9 C
1
9 a* L' ?; P- Gc、创建请求4 c8 {- v- i! y/ g' T Z
3 [* }2 N- a, vresponse = requests.get(url)
) l5 d3 o* l, S* {1 k7 t( A& e1- j' x# H8 a) y4 p T, P" V3 }$ h5 W
d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)/ B, u/ a( Y6 K
1 X! ^6 n# a S3 p& u8 P1 O( o
print("状态码:",response.status_code)' g7 X; z# r8 x; @
1# A) V! B* N% K0 N& d
当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
. p4 S; q$ F S. E$ U% je、得到网页源码9 O* \# I: X+ N
, w4 V7 q* z6 k3 }1 K% P8 z
print("内容:",response.text), c& J9 g8 _) q: H" Y. l/ g
1. p* f- F# u4 N# Q" x
response.content是response.text的二进制形式
0 N7 E. ?8 [# ]0 o2 k |& B' {
1 g* g) n% X5 M至此,一个简单的爬虫请求就算是完成了。
$ \0 X5 [$ ^' s6 e当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
0 a* F) l" T5 ~f、解析网址
" Y6 n9 \' F- ?" @1 K D2 o刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用) e/ \% b# [- V6 O& d: j
BeautifulSoup:; W7 g! A% t+ W, L0 G: b1 q
首先导入需要的库文件:1 q0 t7 I% \' s" H
. i- k( W0 G6 t- Jfrom bs4 import BeautifulSoup/ a. L% | A5 \ x5 x' u
1
4 r6 \6 M8 r7 ^0 j/ K+ b然后对上面请求得到的response进行解析:
. R% H9 K" k) N0 r' N
" J: g, N# I( G3 |html = respone.content.decode('utf-8')) x* _# A+ u# }. t
soup = BeautifulSoup(html, 'lxml'), p' l- G( ?- [. X7 d7 m/ P6 V
1% A! T7 D% {. C2 u1 }) Z
2. ^2 G+ V+ U# S& ^' m, O2 I
以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:, F) U; W9 b1 V, M2 k: w+ G
# 获取head标签+ ^8 s7 O% Z2 _: t
print('head标签内容', soup.head)6 g( x' g: X( d% l1 n+ T+ Y3 E* Z
# 获取title标签, s. S$ y; G+ \0 R' L
print('head标签内容', soup.title)( m2 t1 ~# c; f( R; B. t8 `3 V
# 获取body里面的img内容" Z8 i* U: |* z2 E2 g
# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
: w7 X) Y/ B( p; [2 r$ [. P4 |* mprint(soup.body.a.img) + \7 g3 W6 F. }. n/ Q
# 获取所有的img标签 使用find_all()搜索整个soup对象4 O0 S! [6 t5 |( a1 f
print("获取所有的img标签", soup.find_all('img'))# j% `. M) c* N
# 获取标签中的属性src地址# G; ]/ L: _, e% M) }; Y
print("获取标签中的属性src地址:", soup.img['src']) # 注意:英文点号都只能获取第一个值
& ]7 N6 D# V% E4 S0 V1 v2 k- c% _, Y9 {$ u9 j. q0 s
6 q* a; N" x5 Z! m1 b# 获取soup的name% g3 m( M! z. Z% E K3 l% y O
print("获取soup的name:",soup.name); [: C7 k: o9 K' {7 q2 ^0 x
# 获取a标签名
" q% h1 N/ Y& o# g. Dprint("a标签名字:",soup.a.name)
# }5 R4 s' c0 U7 O& ftag = soup.a% ]/ W) g: d6 i v
print(tag)2 @6 i f& U* a3 M+ _( `; t
# 修改操作 a标签改为b标签1 k! }; [( k, g9 K
tag.name = 'b' # 赋值后<a> </a>变为<b> </b>. r) [# _2 B6 c' A3 W
# 输出修改后的内容! s- U# H# I" S+ u7 F- C
print("输出修改后的内容:",tag)
* n( o) b! I: b) v9 c# 获取全部的属性 attrs
9 p: U5 P. v+ M& {9 _print("tag对象的全部属性:",tag.attrs) # 只能得到当前标签的属性(不包含下属标签)
" Y' s. ~/ S) p$ p
5 a0 f! e& q! e# F' a# 获取属性的class的值 根据键取值
. |$ d. D3 Q% \. ~$ dprint("获取属性的class的值:",tag["class"]) Y" Q/ b' }6 w7 ~+ g e$ O
: N& W& c; M% M2 `
) |% I- I, d+ S7 u- c; ^
7 P2 C# L( v! \( O: g( {, z- Z$ G) c7 a* T5 A+ s
"""针对获取的标签属性可以进行增删改查"""
7 A; t7 |" c6 h+ n* e8 N) w: ]# 修改
" h* E* M. L* @tag["class"] = "Logo"% R& h$ k, V4 A( S& t
print("tag对象的全部属性:",tag.attrs)
4 H5 ^8 w/ O3 y' y( {* B) ^ s! W# 输出属性
, M, ~# A" Q+ E0 K5 N4 B8 J& |0 Oprint("获取属性的class的值:",tag["class"])
6 u0 N0 i0 Q9 V( ^# 新增 属性id 赋值logo
( x% S2 y, ~7 K, ^; s% m! ] C4 itag['id'] = 'logo'& A3 ~: A6 Z, M, z- `
print("tag对象的全部属性:",tag.attrs)8 X- \" B( C* X5 k
# 删除属性, S1 }. t) L' _/ k( T' A
del tag['class']5 z% D5 ]. E2 B( Q6 b7 h4 X& V- D
print("tag对象的全部属性:",tag.attrs): }# M) y* a* h7 ^! d* D
* f0 i" ?! t0 Z3 z2 s- w
& W( B8 T* G% f- p. S* `3 l3 E" |1 L1 n6 H- ?1 C ~: z( r# Q
"""针对内容操作 (只针对标签,对属性无效)"""
! c; e/ F6 O- i3 A% t# 获取title标签内容$ b* h( s3 Q0 P0 A0 P9 {0 l, h6 ]
tag = soup.title2 p5 N) w9 ]% ?. g1 W, V8 P
# 获取title字符串
4 f. b; ^- ]3 I+ |; c* iprint("tag对象所包含的字符串:", tag.string), C* O; u; f G& Q) l
print("类型:", type(tag.string))
4 |9 U3 l8 D5 Z* _# 替换内容
: N4 v0 t7 s( m4 Otag.string.replace_with("你好")4 O' p: N& d, S7 _% z5 o
print(tag.string)
, L$ @! ~, m6 ]# <!-- 学科建设 -->! {; D; N$ k! P" }
# 获取注释文本内容
, e- r& Y4 P( m+ p2 X1 `' \markup = '<b><!-- 学科建设 --></c>'
' |! m) E3 q4 S" |$ }6 Ysoup_comment = BeautifulSoup(markup, 'lxml')3 d$ M N; u+ B) ~9 _9 V
comment = soup_comment.b.string # 以markup第一个标签作为关键进行搜索
! T i9 C7 m/ q& v, `print("获取注释文本内容:", comment)% }, q7 F7 t6 m
# get_text()4 ?; u) O [5 s+ q. q
print("title的全部节点:",soup.find_all("title"))0 r5 V" ?6 k |& _1 v- G
print("title的内容:",soup.title.get_text())
& h4 v& c' A6 x( i ^* n"""查找ul元素标签"""0 F5 L9 U; H3 _/ j! W
# class是关键名,匹配时后面必须加下划线_2 s* R1 s7 m, C3 H3 Q' z, v- x
# tag = soup.find_all("ul", class_='menu') # 按照css类名完全匹配
8 _2 z1 i9 ?" q* m2 W+ K+ h& v8 m# print(tag)
/ H) d) E( ?; y% X0 O" P6 ltag = soup.find_all("ul", id='menu') # 按照css类名完全匹配0 W! I; _' a0 ?5 X/ i/ P! ~
print(tag)
9 E% K w8 u$ s$ D# 查找名称为a元素的标签内容
# S3 J& i# t1 I! s$ Etaga = soup.find_all('a')1 g% D; s. L' F. r
for tag in taga:
- d( ]6 M% E. q: | print("查找名称为a元素的标签内容:", tag.string)1 {9 x7 Q# N: c- O0 i
# get 获取属性信息 获取整个页面的img标签图片和src属性值
* V& T6 x: O9 j$ s3 Y3 l1 ltagings = soup.find_all('img')
/ v' P9 [9 K% |5 |print(tagings)) b) J3 o+ q4 n n+ T
# 循环输出图片地址
: ?( C% p% I( ?$ x* R, }1 gfor imgsrc in tagings:
N. B2 s z! G' u8 u! Z2 `- U print(url+imgsrc.get('src')). I( X3 B- Q* x; Y8 j
% u! L' U1 n% m- L2 R
""""属性只能做为参数,所有的操作只能针对标签"""0 E9 e9 Z# q$ E U% z1 F3 a+ u
0 I4 h7 {. U7 k+ S0 d3 V# M$ u
etree方法:% V2 X3 d+ B- |' Y2 s% J" q
导入库文件:
2 T! j; p2 D# D8 Q( l
, l, a$ s1 Q" y+ a( d2 Pfrom lxml import etree9 d0 d1 ]' N) U- H( g- G1 }
1
6 r, N# y& z6 e2 Z( k9 q解析得到的response对象;
}5 u" [7 f+ u1 G4 @) E0 A& ~+ F( R) J
# 设置response的字符集
! u- W2 w* a6 v- X* [% _html = req.content.decode('utf-8')1 r7 W8 M$ @9 U4 ~8 G
# 解析对象
4 n/ G8 I+ l+ f& Qhtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
. v& J5 j |2 o6 y, ]5 M. s; p* L" `
# z6 d5 d- t6 g6 [常用的方法:7 W# J$ v. i1 ~, s) }% D! U: s& V' n
6 l- g: H) R* c; [- W- K( a2 l( z# B$ V" ^# m" A2 {
# 定位head节点(元素) H8 F5 o+ r0 h: q
result1 = html.xpath('head'). e. E0 U* d6 v1 b
print(result1)
1 K$ h7 X* I# N# 定位title节点; p# h9 P5 E, u2 F3 f" H
result2 = html.xpath('/html/head/title')
' C/ f2 u5 \' j1 z; A' B7 U9 z) gprint(result2) u0 r4 i9 n4 @
# 搜索节点 title节点1 @9 O, q; t# ~) _/ b- ~# i
result3 = html.xpath('//title')
/ s3 Q6 G* T% m! L) B0 m$ ]print(result3)! q5 z5 A- O% q3 W; e% u
# 搜索title内容 text()得到文本信息
- K8 f% w/ v: m3 aresult4 = html.xpath("//title/text()") |: r- K( n6 ?& |1 \8 t
print(result4)2 e( c0 Q, v' |+ L0 v/ X2 `( j
# 搜索div节点
5 t; o; n9 [4 T; x" a& Eresult5 = html.xpath('//div')+ c% A) B' u* D/ S/ ~$ r2 @ \2 j! R
print(result5)$ b! v6 `" g8 \) x }5 }/ j: Y. u" h
# 搜索div节点 并用class属性定位$ g1 E! B5 }! g4 f# H9 ?; ]. F
result6 = html.xpath('//div[@class="news"]')# ~, V; Z8 M: K; T+ |) s6 g
print(result6) U0 Y! j. C5 c/ m& X! W
# 搜索div节点 id属性定位
! l, y9 b8 c7 \result7 = html.xpath('//div[@id="news"]')
, B* v8 C+ R! }/ O8 S( F5 ~5 Lprint(result7)
) P' Q3 M9 h: B! U( N& h! y/ \ D: _# 获取列表span信息8 {( ^2 o4 ^3 S( x G7 K
text = html.xpath('//div[@class="news"]/a/span/text()')
; Q! Q* p4 O; ?. O6 a4 O; W. Oprint(text)
8 i/ H) A) r& U. H/ J, M; \; k1 m& ]$ M1 O
g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
! M% X; x1 d# I' J7 S7 D7 e* }保存的方式有很多种:
1 b9 Q6 \+ N; ^1 S& E! h. g1、保存至文件
3 T5 _; _( E: {csv、json、text
6 e+ s5 B6 E! t/ D: R2、保存至数据库) F5 b% A9 K% V3 c9 S9 v8 E$ @
MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库) 关于数据存储后面再做详细介绍$ }0 U$ o+ ]; O- P
% Q9 Z: z* p& h5 @/ d4 K( C
, m+ f* r" ?" o a1 i, _# I( Y* I————————————————& j( V, Q1 d$ [* L; z1 d0 r- j
版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。- m$ y6 E! e+ T2 [. S' m
原文链接:https://blog.csdn.net/royallucky/article/details/1059304739 b2 e& S$ L1 Y1 F1 u+ O; \2 e5 ?
, G' y+ O$ g8 D8 V; H1 u6 l- T. ~: w. C
* h3 S9 h9 }6 f& w" x2 K |
zan
|