- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 564697 点
- 威望
- 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年大象老师国赛优 |
5 O/ e( ]$ p% r8 A+ e6 M
& v6 | j1 t* s& c1 ~& {
8 q9 ~9 W0 `% ]/ N2 v0 D/ Q手把手带你5分钟搞定爬虫(聚焦爬虫)
& p" G7 u* S. E2 S& k
1 W; v9 m. ?% F+ V; l爬虫的原理
, S$ R$ q, z l$ }1 J6 Z# \0 r, ]$ F& W: ]1 {+ y
对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
8 Z0 u) ~4 [4 `; {9 @4 m+ J% c把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味
5 V0 A2 O4 S/ D) X& g所以说爬虫分为三部曲:/ _9 Y$ u/ A0 e8 N& t
1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)9 G" q5 e5 N. v" F8 G0 G9 p) [1 U
2、去找到你喜欢的食物的位置(得到目标地址)# \5 g9 p4 y4 C. B0 I' B) @' J
3、把食物搬回家去(解析网址,获取数据,存储数据)
. A& g" w* u! h' D, X5 @8 o7 g它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
5 n' k' E$ M% p3 {& O) Pa、导入需要的库 requests
' z h( c3 s. D6 K! O b+ d. t
( ]( o |( O2 Fimport requests0 P% g0 O1 z& z- [- g2 ?
1
4 b5 u9 d+ n$ b2 j/ W- I- eb、明确你要获取数据的网址(这里以百度网站为例)
5 W; ^: Z( T d7 a" L9 }: |
0 V2 B: M5 }7 l7 }2 ~url = 'http://www.baidu.com', C' Y8 D: {4 {6 l- z P0 ]
1
" S" \! q3 U: s- J& V' `4 F4 n. Zc、创建请求 a7 f0 B4 Q5 {6 A
2 u: N0 o, v* L; h. Presponse = requests.get(url) g8 W) M2 M7 j7 ^
1+ {" v" I1 n! E0 O; i
d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的): h- u1 l+ F# K/ {% `7 X; x$ t+ B
0 o D4 E. m; J
print("状态码:",response.status_code). E& N( ]) z; `* n/ G/ z9 P
1) j! m% b( d! o6 s5 D6 e7 }, Q$ x
当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url; E; w* G# @4 i" ~/ @
e、得到网页源码5 u, ?" q4 V5 c8 L1 e( A, J. P5 a. B
6 w5 z7 R! m) Y& c( h* w
print("内容:",response.text); a6 f6 y! c, I5 t0 k: p p, N
1
8 a" _5 x7 X0 _! ]* a4 \' {response.content是response.text的二进制形式
& T! I y5 G+ p2 T, P) G
/ N* ^8 v! v j至此,一个简单的爬虫请求就算是完成了。, j' V7 u. b0 M7 F: J k8 _
当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据1 y2 T% ^- c( j) }
f、解析网址
" K) g4 T7 S0 ]刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
. c! ?5 E; p# h' t# H, A6 }BeautifulSoup:
4 W, h5 X4 x' `, L. N首先导入需要的库文件:3 {) \: Z6 G+ ~, O& o
3 @: W* K Y0 P C x* c! g+ {from bs4 import BeautifulSoup, z; R2 }. C9 n+ l) t- E
1) |2 k G Z8 d
然后对上面请求得到的response进行解析:
8 w1 t4 |+ R% W7 j$ [5 @- C" a# j$ e8 v2 m8 u8 Z& M1 {& ?" M
html = respone.content.decode('utf-8')
R( k/ N, o4 T* q3 T) wsoup = BeautifulSoup(html, 'lxml')5 D( |+ Z5 Z7 _) I; ~/ k+ p
1
$ e8 C+ y; _( r7 v8 n$ n' Y+ _) m2
K3 H) M2 k$ B6 E: t- R以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
% i" S, ^1 W7 w% J3 U# 获取head标签
# X3 m, C5 @3 N, g Lprint('head标签内容', soup.head)
1 E# F' L5 e. I9 F$ s# 获取title标签: T( R( v) t# r5 @$ ?$ P
print('head标签内容', soup.title)
: S' P% f5 {; T, C1 t# 获取body里面的img内容
( w" |4 j0 q+ f# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)3 `. d) Q6 ~: O* P. |3 t" n9 U
print(soup.body.a.img) # G% t: I2 w7 x/ k) z" b
# 获取所有的img标签 使用find_all()搜索整个soup对象$ ?: J$ v! a0 t9 y
print("获取所有的img标签", soup.find_all('img'))
' w, F6 ^$ _& e+ c |6 L# 获取标签中的属性src地址 s7 a4 t' E" U
print("获取标签中的属性src地址:", soup.img['src']) # 注意:英文点号都只能获取第一个值4 @+ r( M$ [, l' }: _
& I2 t5 r5 |, b" d
8 L2 p* F0 E2 P! S# 获取soup的name
6 g# V) u" N. a+ o( y0 i( {print("获取soup的name:",soup.name)
$ O, _, X8 Q2 Z6 p* E# 获取a标签名
$ d Z' }+ T2 _; t" [% f# @print("a标签名字:",soup.a.name), Z3 n* x: I! H) `
tag = soup.a
$ v; b$ f* k8 A: }print(tag)# i4 j2 X( p/ g3 H1 N w" t9 s
# 修改操作 a标签改为b标签
2 B9 i4 n, I$ D8 O7 C- Ctag.name = 'b' # 赋值后<a> </a>变为<b> </b>
/ G8 @1 z' [# c/ Y/ j! c% h8 e( J4 d# 输出修改后的内容
" |+ l; Q5 I% @( oprint("输出修改后的内容:",tag)
4 e4 C# X! H& W8 ]. i$ l0 R M# 获取全部的属性 attrs( J3 d4 N0 Z+ S9 |5 ^, S$ _( ]
print("tag对象的全部属性:",tag.attrs) # 只能得到当前标签的属性(不包含下属标签)
; M) v( X- L. T- H% s/ O
6 K& @) ~8 r! J6 N( Z# 获取属性的class的值 根据键取值5 z1 B9 O& l7 e6 W4 ~& f* t
print("获取属性的class的值:",tag["class"])2 u6 h' u0 Z$ N5 R) X
- J+ V4 A8 ?, S
" c5 W; x" `/ w
! I* L- ~4 m7 W( q% F) r/ E2 b0 f3 m+ Y) M
! ^3 U5 t# ?8 n. [3 W$ i"""针对获取的标签属性可以进行增删改查""" Q& a" Q3 N+ S. @/ N
# 修改
# \9 f2 w; W9 q) D4 Utag["class"] = "Logo"4 H4 I) E( j ?% W$ Z* o7 g# \) |
print("tag对象的全部属性:",tag.attrs). J6 y% o* U3 z1 N: S. g# G7 ~
# 输出属性
) u X; h8 A1 o# \print("获取属性的class的值:",tag["class"])0 W: O4 v3 r* j
# 新增 属性id 赋值logo
) |* Q4 A% P: {( }( e0 U- Otag['id'] = 'logo'
8 c$ h2 u$ k5 F3 sprint("tag对象的全部属性:",tag.attrs)
/ K8 o! m0 H, J0 Q* f: K# 删除属性
1 P/ c/ b' z5 A, Odel tag['class']: } V9 i, x/ l7 L2 s9 E+ T
print("tag对象的全部属性:",tag.attrs)
" z4 c% r7 Z" T# p% ^7 v
4 W; w+ l: o; I& Z4 w8 h+ @5 v2 n3 k# _
# N- G0 _: r: i+ ^: R
"""针对内容操作 (只针对标签,对属性无效)"""
# t, ?% O5 ]6 V4 A( N# 获取title标签内容( c, @& _* e9 r4 p5 C7 _% Z' {
tag = soup.title
4 s m- e4 G1 I) j! x5 g# 获取title字符串
0 t$ Z# r% a5 [1 p9 Z/ Wprint("tag对象所包含的字符串:", tag.string)0 e/ t ^6 s( g4 m* f2 I
print("类型:", type(tag.string))' y( v. m6 E. P# l+ y) E
# 替换内容
. U* n5 X _* ~! c6 [4 ytag.string.replace_with("你好")
, x/ p# c& E ]2 X( ^9 Y' q. d9 }print(tag.string)
* N1 ]9 Z+ m, C& e; @- S! N# <!-- 学科建设 -->
0 }% x7 L( F0 K5 o# 获取注释文本内容- B# \, u) {" V+ N: `
markup = '<b><!-- 学科建设 --></c>'
( w" d3 w m O$ w3 M1 ]soup_comment = BeautifulSoup(markup, 'lxml')
) n6 `9 M8 f1 K5 a9 n0 C+ W: Wcomment = soup_comment.b.string # 以markup第一个标签作为关键进行搜索
2 ?" z2 h' y3 F; i4 b+ }3 iprint("获取注释文本内容:", comment). K/ e4 O8 X8 S* H* v
# get_text()
& m" |" D8 ]! ^. W( e7 _print("title的全部节点:",soup.find_all("title"))$ k$ _! e+ P; ^+ ` U- J3 S
print("title的内容:",soup.title.get_text())5 j9 k# S" m' M }" A. L' `
"""查找ul元素标签"""
: l/ K5 W8 ~! ]. e2 C6 x3 S8 b7 M# class是关键名,匹配时后面必须加下划线_
1 z& u9 \/ t& l) k- C6 E# tag = soup.find_all("ul", class_='menu') # 按照css类名完全匹配/ C! ^( [8 b- I# {
# print(tag)
/ E# M2 K' k: vtag = soup.find_all("ul", id='menu') # 按照css类名完全匹配
% ]' ?& X0 D- Y* aprint(tag)$ o; R* {2 P+ s
# 查找名称为a元素的标签内容
3 j5 k a) f% a4 w$ Otaga = soup.find_all('a'). N8 E s) B# s% D3 X
for tag in taga:! A, V- l; [% l
print("查找名称为a元素的标签内容:", tag.string)' O% c0 B, ^: P' H
# get 获取属性信息 获取整个页面的img标签图片和src属性值( Z* m0 r8 }( }
tagings = soup.find_all('img')
k; V) F: l, C) e( o; {) sprint(tagings)* G( |1 R# Q6 J0 g0 w" ~
# 循环输出图片地址/ M% [6 M' C& H8 u. o2 F
for imgsrc in tagings:
3 S3 ]4 y6 H1 F print(url+imgsrc.get('src'))
* s' \5 c: B; s4 I0 e3 e" v% x* j/ e. b
""""属性只能做为参数,所有的操作只能针对标签""" U7 _3 I: a% j; @( N/ w7 o7 c5 Q
" t% g+ g" i! r8 Uetree方法:4 S4 Y! Y! a- v
导入库文件:5 [" j7 C* R' C# s: w1 K
) W5 [& d9 i' a3 W) B
from lxml import etree
: [ h" Y0 H" h0 V1
. v6 C, }' \5 b0 b7 p解析得到的response对象;8 s6 P+ }% F7 @" M& K; e
/ j2 `2 [. E/ z, N9 |; n# 设置response的字符集
4 D, {2 ^! m7 W& _: ^5 P6 Ihtml = req.content.decode('utf-8')9 l- p0 g: a4 H8 ~
# 解析对象
$ }' v" V& x" R5 `6 Y Ghtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))& H* \ _# Y; _7 o6 J( i! [
& c" M" a7 J1 y0 \4 v& u0 a
常用的方法:7 @" [6 F1 p3 a" |9 G3 ^
1 {+ E' ~) G- v$ q
% p" ` [6 g% W: C/ f' ~# 定位head节点(元素)! E9 y) A' y$ D) E2 _. d' w
result1 = html.xpath('head')
" ^/ c" L$ r4 E3 X, T) F" C! X& k+ c6 Oprint(result1)
) r' g3 p$ j0 ^8 h+ d4 i2 p# 定位title节点
( ~# \0 e2 }& v, K( yresult2 = html.xpath('/html/head/title')
y# H, _1 x( {6 Bprint(result2)
' c$ e# V9 l2 f4 J( D* ]& J# 搜索节点 title节点$ @: O/ n7 E; v% b) b+ l
result3 = html.xpath('//title')
O2 z. h% D# @$ Dprint(result3)
# S6 S9 t p. M4 x5 i7 \+ y( v y0 u# 搜索title内容 text()得到文本信息
8 m8 V) f9 v2 E; Wresult4 = html.xpath("//title/text()")
6 D6 V& ^- J+ e6 sprint(result4)/ l* V! o' R5 H- @5 S) K
# 搜索div节点% D" q [; I! I% A* Q
result5 = html.xpath('//div')2 S m2 o6 S7 U" v
print(result5)+ U) s2 l1 a6 t
# 搜索div节点 并用class属性定位" d% l. C5 q8 r8 {2 R1 n! G7 I8 `
result6 = html.xpath('//div[@class="news"]')1 ?, a) L q" M6 q6 s1 q' Z
print(result6)8 K3 F( m/ ^6 M- e! p
# 搜索div节点 id属性定位2 I+ K% v7 K$ J2 y- X- w
result7 = html.xpath('//div[@id="news"]')
% W4 v2 a1 P0 C" kprint(result7)
: I; b9 Z6 m- F2 e: ~* G" O# 获取列表span信息9 P" ~# V# o0 W! _- }8 B
text = html.xpath('//div[@class="news"]/a/span/text()')
% n& F! \: Y" g" d; L* z Aprint(text)
& f" Y5 H+ _! s, F* q0 E% e1 _
( `# Z* Y( ^& k0 D V$ ]8 Q4 eg、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
2 R) a* T9 [9 L( }5 A保存的方式有很多种:* ~* j$ k; q1 x! \
1、保存至文件
3 |3 h. d: M7 Ccsv、json、text4 y" o: {- b! v4 I
2、保存至数据库; M- o7 A% D$ W x: r) D5 t( r
MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库) 关于数据存储后面再做详细介绍
* b" M* G9 d# m! L/ n
$ j2 Y3 p. X9 l1 F, f& \3 \& t2 @! C5 N% G* k7 }
————————————————
6 W. J r. n1 R! \6 \& e6 ~' \版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
( ^6 q( Q' k4 `/ f6 m, C原文链接:https://blog.csdn.net/royallucky/article/details/105930473
4 p; [8 k3 q |1 X4 |4 P- ?
! Z. \, s1 G0 F$ j7 _2 \3 d! A6 f7 f( B' A! w9 ?! x, S) v1 j
|
zan
|