- 在线时间
- 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年大象老师国赛优 |
' B7 t& O# E# C0 M, w+ b5 w/ g
6 o& N, \- r- \% ]. f: o % ?/ N- O) @3 T$ r5 q; @9 V# ^! ?
手把手带你5分钟搞定爬虫(聚焦爬虫)
6 R) @9 i" J( f$ p
( V! g7 j; V: o7 X( n, B爬虫的原理
1 j4 r$ r! O/ C6 H, }- x' H1 D6 C. I* u* h/ q/ w$ C! A
对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫1 Z* k1 _# M- [2 A7 J5 l) V! R. M
把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味 |1 R W6 F5 M! i6 O w: C$ v, v
所以说爬虫分为三部曲:8 A) `+ h( c; H2 F* Q4 X7 f
1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)
$ R- W5 J" M9 r' z- w1 _. T+ X2、去找到你喜欢的食物的位置(得到目标地址)4 p; q+ S5 x' F y# x; |. J
3、把食物搬回家去(解析网址,获取数据,存储数据)
6 m; e z4 F* p" o4 E它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)0 H& N7 v3 o! _' i
a、导入需要的库 requests
7 p2 Y' C: \4 K# Z- V5 g% i- u S% T1 S& T* h2 j
import requests" N; Y, h. |. C6 X9 b4 i
16 V) S+ x* l p b% l
b、明确你要获取数据的网址(这里以百度网站为例)
. H* Z5 y8 S" @" C
6 C/ c, U# O; t4 w6 d) `9 t' i: g$ k! c9 aurl = 'http://www.baidu.com'
" K1 W0 k1 i6 N* O1
; _& {& T% G) j- \; p$ K% N) lc、创建请求. K) {% r, }2 i
3 }: J3 R: c! c
response = requests.get(url)
) ^, c8 V/ B: ?5 b2 H1 f: H0 l1
5 j5 u2 s6 ?* V, E& F- O/ gd、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)1 w2 f9 k1 P4 B& f1 X0 C
# j/ l) A7 y, h3 [; |5 M' t# Zprint("状态码:",response.status_code)
: Y& B- B/ M4 H" e6 }+ m1- P; O& }8 Z& D& _1 s( X
当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url8 S$ v; t. x$ P& W$ b3 H
e、得到网页源码
7 s3 ?8 K; l: G% M5 w- V' R0 v( u N0 {/ o) \& c9 g3 C
print("内容:",response.text)
3 i5 }! X* Q+ b m3 r s1& T5 E) E3 W, m" J+ M% @
response.content是response.text的二进制形式
8 c9 z4 e) l% T) z7 A9 f' P1 L1 D
4 g6 }2 G7 C9 R$ S* s3 [5 Z至此,一个简单的爬虫请求就算是完成了。4 W6 f% n9 q% k; X" _
当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
$ _4 g E. L, M* R; M3 q& Jf、解析网址" C0 i) n T1 g; s: J
刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)6 d5 W: O6 g' a6 }& d# @ y
BeautifulSoup:
0 W8 K @9 r l) {7 D& H首先导入需要的库文件:
" ^6 s" m) c5 F R$ O% q# z& M' U$ h+ E7 B: a
from bs4 import BeautifulSoup# \; V/ u3 }& Q i4 g7 u/ q
1
/ K; e5 y9 D- X$ @; y- H3 D# \然后对上面请求得到的response进行解析:
, v; ^+ X( o/ C3 a( p$ j5 P1 d7 y( y" K/ X% Q- L+ I7 Q
html = respone.content.decode('utf-8')
: F' y5 N! K" M* ^2 B7 usoup = BeautifulSoup(html, 'lxml')
! Q3 }1 Z- ~$ ^" [7 {3 ?9 j, O4 f' R1
1 x3 S9 Z9 C+ |. K21 \2 V$ ^3 C% G
以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
1 N8 e- u3 e. @6 I8 @: K+ ]# 获取head标签7 z6 C3 {0 i+ _
print('head标签内容', soup.head)
! y" O! a4 t- g# Y8 @# 获取title标签
' h3 ?* n; u5 Q- R2 a6 Y p- Dprint('head标签内容', soup.title)' t% g- E7 M. {0 N6 R% ?: s
# 获取body里面的img内容+ x' K, V% {; Z8 m' q
# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
& v, Q$ { Y( Z. R. F A3 c* sprint(soup.body.a.img)
3 @5 N+ ?6 j6 c# 获取所有的img标签 使用find_all()搜索整个soup对象' q) E4 o+ n' b3 z& h% Q
print("获取所有的img标签", soup.find_all('img'))/ U6 Z/ L4 u9 K. O8 \9 L
# 获取标签中的属性src地址& U ]+ Z) I0 H b C
print("获取标签中的属性src地址:", soup.img['src']) # 注意:英文点号都只能获取第一个值; V. |' J; _$ @: e7 c7 C; H. e7 [+ G0 Y
/ A q3 c! p3 X" k8 E3 p' T
$ U4 j5 }9 x! T# 获取soup的name9 i" F3 a6 @2 s e4 \
print("获取soup的name:",soup.name)
# |# p6 y# ^' Y4 o# G# 获取a标签名2 T3 d* b) U0 _
print("a标签名字:",soup.a.name)$ n6 W/ I# Q6 k% j
tag = soup.a
' H7 K& v2 U& E4 u+ |1 ] }, xprint(tag)
o/ b% k: ` R3 m6 G4 [, T# 修改操作 a标签改为b标签% k8 H9 M& x; b A# N' O* |
tag.name = 'b' # 赋值后<a> </a>变为<b> </b>; K5 ^+ C) Q: z7 E8 m+ c$ N
# 输出修改后的内容' B' Z$ B$ K) b% g; ~6 U
print("输出修改后的内容:",tag)9 T5 ^8 b6 Z: R$ d; Q" q
# 获取全部的属性 attrs
9 f O& r9 h6 |9 B5 D3 U4 Uprint("tag对象的全部属性:",tag.attrs) # 只能得到当前标签的属性(不包含下属标签)
; f: G `3 K* a8 [0 P5 x! e
+ ^. ^8 i' g6 t# `' ]# 获取属性的class的值 根据键取值
0 ]/ q$ i) Z) d/ Kprint("获取属性的class的值:",tag["class"])0 m, F' C7 k, S) c
( b. |+ d9 ^3 b% p% {8 E, [8 s) F2 u+ q0 [2 h: W4 p2 A
9 e9 K% q6 y; w) e
' i8 i# V: ~+ V$ S0 s; E `( m& Y"""针对获取的标签属性可以进行增删改查"""
9 P8 ~$ ?& Q$ I/ A# 修改
* v3 [' w5 K! vtag["class"] = "Logo"& I) G& z% z" T1 t9 B w- E
print("tag对象的全部属性:",tag.attrs)( l# \( E% h3 N/ ?: @. t0 L; m: ^
# 输出属性& `& e0 U' r ~ W: g
print("获取属性的class的值:",tag["class"]): t J. z9 |5 n
# 新增 属性id 赋值logo
3 P0 {/ }! H* [2 mtag['id'] = 'logo'. Q8 r/ K8 M; v8 k, e& b/ r
print("tag对象的全部属性:",tag.attrs)! h. i5 m$ Z5 {% V, n% L0 H# q
# 删除属性/ f) J. h& w5 w, C! V
del tag['class']# p* ^% L- y3 W2 P2 P- Q# A
print("tag对象的全部属性:",tag.attrs)! W# ?8 ~7 P3 z" `) U
0 i/ X6 t. q, X/ `5 y1 q7 F8 x2 C8 `6 V0 }
% I+ Q$ M6 M b
"""针对内容操作 (只针对标签,对属性无效)"""
, v) k- m/ j- P9 ]# [; y2 E# 获取title标签内容, O& G8 I9 x: E# J2 N. `
tag = soup.title
" g. H4 M1 D( N, \2 J$ M# 获取title字符串( q1 \% M& r. h# c: y' U, y
print("tag对象所包含的字符串:", tag.string)
' K9 p- x6 F" sprint("类型:", type(tag.string))
/ A0 X! l ^3 A. L# 替换内容
. U; w6 K; t, U& P+ g+ a- gtag.string.replace_with("你好")
: B, P; N3 a+ T* l; bprint(tag.string)
6 |# Y* U- \, a# <!-- 学科建设 -->8 g6 Q& D1 y# X( }
# 获取注释文本内容
* t/ a; k3 y$ wmarkup = '<b><!-- 学科建设 --></c>'3 F$ x @! a; p S7 g3 Z0 U
soup_comment = BeautifulSoup(markup, 'lxml')) s2 L! L0 X* J. V
comment = soup_comment.b.string # 以markup第一个标签作为关键进行搜索
, O' N, a! N- |/ A! x* Q( Rprint("获取注释文本内容:", comment)9 f$ h. G9 g. t5 u' A r4 x# a/ c
# get_text()9 A/ ?( U! g6 c$ ?
print("title的全部节点:",soup.find_all("title"))
9 ?2 e5 X' ?5 c7 D. i3 lprint("title的内容:",soup.title.get_text())- l- w& A" z0 H# X
"""查找ul元素标签"""
* \; Q3 l; y- z# class是关键名,匹配时后面必须加下划线_
% r- {- \$ I" c7 D4 e( V3 L# tag = soup.find_all("ul", class_='menu') # 按照css类名完全匹配
! e( t& p& @7 A2 A# print(tag)
. t+ U- |; n7 w$ N. ]8 Otag = soup.find_all("ul", id='menu') # 按照css类名完全匹配
- i9 [; l2 [1 r* y/ qprint(tag)
: V! Q5 P) q `, }7 m# 查找名称为a元素的标签内容* l% \; l& u4 u; ^& c% ?
taga = soup.find_all('a')
- R- [; T0 W' O0 l7 Xfor tag in taga:( X$ N# w k) w' L9 D. U$ R
print("查找名称为a元素的标签内容:", tag.string)
& Q; m0 x8 M5 ~ r \# get 获取属性信息 获取整个页面的img标签图片和src属性值
. [5 M/ t) v; f% `, _, S; stagings = soup.find_all('img')% D2 r; V) b( v
print(tagings)
$ p0 v! |7 y0 @+ g# 循环输出图片地址! L/ m T, n7 K% {
for imgsrc in tagings:
! c4 W2 H8 e8 [& [, n print(url+imgsrc.get('src'))8 }6 ]) h/ y: Y- m/ }2 i4 K
9 g# Z! B8 C8 R7 m" R/ W4 Z9 y/ V
""""属性只能做为参数,所有的操作只能针对标签"""1 p4 Z8 M- f+ g6 C; r6 J
9 {! m' G3 G5 O5 v
etree方法:5 W7 I0 s" p- I7 u c6 {9 h2 M
导入库文件:% @- u5 z" }3 X& w, z" ~
! U# X2 g& ]- h' P) t8 @4 B
from lxml import etree- _6 z1 m: F! u
19 J# C2 {3 [6 G8 K$ ~: ^
解析得到的response对象;3 j, d- s8 ]+ L$ [3 \% U7 g# d
. z! |. M8 w$ K4 G6 V* a# 设置response的字符集1 C& z! X1 N3 ?" k
html = req.content.decode('utf-8')' ?: \- _( _# F- ?
# 解析对象* Z W/ O7 |2 m5 _
html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
4 ]3 f5 c2 O( n/ K6 Z1 j* i- x! p0 j
常用的方法:
+ y1 Q1 k/ B6 P1 M+ h0 h8 e) i1 ]% Y3 h) `/ P& g" b: q
) N8 j* r; a1 ]; d+ l
# 定位head节点(元素)% E% B% q$ a& a+ G! T# q0 e
result1 = html.xpath('head'): l: M5 a& g8 D: U; ^
print(result1)
- e+ P5 G- O( k. Y3 }( @6 x" k( `6 W# 定位title节点& T+ I3 _) L& V* U V
result2 = html.xpath('/html/head/title')! S' w: Y. ^$ t7 \' l& e
print(result2)+ {0 M1 e4 z* Y# q! |
# 搜索节点 title节点( T3 P3 b$ B @( `* z
result3 = html.xpath('//title')
" R1 Q# ?! Z4 `, m+ w" hprint(result3)
5 X$ X/ o+ c0 `- l6 m/ a# 搜索title内容 text()得到文本信息6 Y% O5 a( |) M2 u
result4 = html.xpath("//title/text()")2 R1 x+ ?& A/ j, g. l
print(result4)
: e: X- `2 P" s# 搜索div节点
' \+ V1 n/ }: S, Hresult5 = html.xpath('//div')1 U. L( C2 @3 F6 N
print(result5)
) { n& i- [7 [3 ]/ h' x& j9 y# 搜索div节点 并用class属性定位
h7 o; A8 X0 n) Qresult6 = html.xpath('//div[@class="news"]')
. B; x5 F: Q. t) R7 g- eprint(result6); N& p2 E7 k! z1 h
# 搜索div节点 id属性定位$ N5 U1 w6 @. e
result7 = html.xpath('//div[@id="news"]')
2 \4 F/ O9 }. B: _print(result7)* }* W; V' N5 \& y2 E" O
# 获取列表span信息7 B+ y6 r( P/ h& ^7 g4 k
text = html.xpath('//div[@class="news"]/a/span/text()')
% y- w t$ l* ?1 }& G% L$ H j6 M Hprint(text)5 y) N5 d/ x2 e: M- Q
3 |4 L1 d7 B T/ F: g
g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
( j- Z3 y0 ]0 X5 G保存的方式有很多种:2 i" l3 I% J* ?5 ^
1、保存至文件
/ l1 @" t8 }3 ^6 lcsv、json、text
9 X) S/ k3 l" ]* Y1 k2、保存至数据库
. e. m6 y, q# A0 kMySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库) 关于数据存储后面再做详细介绍
. R5 c- l: O+ J8 F3 C/ Y# J3 A* ]+ @3 a# q* M
: P3 o6 A' |0 M4 Z6 R5 Q5 j
————————————————
$ z1 T8 e- U6 K6 X v& K( s版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
8 c( _& m$ t* I原文链接:https://blog.csdn.net/royallucky/article/details/1059304732 g$ H( b! j" i1 f: u# q0 V
0 f2 @! t7 o1 \- E7 U* D" J) X6 }2 R4 G5 N& a3 p
|
zan
|