- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563329 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174222
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
6 }3 d* K: I W. ]2 B2 I( B! A/ }/ c% z4 H9 T# k4 P
. Y; M5 Y9 u- m& X" e手把手带你5分钟搞定爬虫(聚焦爬虫) : ^2 H9 C- X7 e, ?& s% W
9 @! h# y1 d" y( s. b
爬虫的原理
! U: w0 ?! H5 U* ?
7 L: V$ I0 c% `# i4 O9 V$ e对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫# k, E) t2 e% J9 o: O9 ]/ m/ o
把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味. N9 m" h9 _. _9 M9 r
所以说爬虫分为三部曲:
6 t2 ^7 g* {3 I( J! p1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)7 [* k; q8 |; _* w+ U
2、去找到你喜欢的食物的位置(得到目标地址)
3 V5 b, B9 O! P7 P3、把食物搬回家去(解析网址,获取数据,存储数据)4 b- p/ @) G1 l
它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
8 N8 H) e$ Y1 _6 ca、导入需要的库 requests! o& t, B$ n. f2 V" ]2 m) t
9 q( m/ q F: ]$ u, N
import requests
- _8 A2 t9 E8 ~; ~4 p5 z0 |1. S( [ f2 h4 C- q# |
b、明确你要获取数据的网址(这里以百度网站为例)
! `/ W0 n9 V/ r* x8 y( H. l9 I, G. \3 F" x+ G) Z
url = 'http://www.baidu.com'
3 b, k2 q; E' ^% Q+ N1
3 {6 T! k7 x5 V6 Y% fc、创建请求9 y2 T2 U# G M: L
! C9 B" D. w9 T" T$ nresponse = requests.get(url)3 y- J* D+ Y& Z5 m* m# D
1
# o8 O' E' d, e0 `* od、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)3 V7 k5 l* _. W& h7 N9 w$ ?4 r
( J/ H: n/ E9 ~, k- {) j5 e# k
print("状态码:",response.status_code)! f$ M) S& b/ o M; s* ?6 c
1* O U3 C! Z! t- Q$ g! @+ v
当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
3 j, W; \- c. b, x; n7 Me、得到网页源码8 ^% j) B6 M4 m) |& A* v
* O% j! @& }1 g; N6 ^) I, r: d
print("内容:",response.text)1 y( Z/ V% F. ^! w3 }7 P( z
18 c/ u# `/ v' {2 o* |$ p
response.content是response.text的二进制形式
; h% T1 V, P+ S" I V4 k) d }, g5 n. Q4 \4 a- h" {
至此,一个简单的爬虫请求就算是完成了。; U( p( n2 R+ r6 h
当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据$ |; W! @6 K$ ]1 d) b3 Z! b, Q
f、解析网址
" m6 i( p7 L* i4 s! f, u刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
1 s0 c7 e, m2 E4 b' o1 YBeautifulSoup:
; z G; x5 r. }2 H. c首先导入需要的库文件:6 d7 A7 Y! [/ }% t
- u; R7 y4 r: s* \& [
from bs4 import BeautifulSoup# w* J& @9 c/ B+ j9 A
1
7 F2 e# j- t" o) ?' Z3 {0 a然后对上面请求得到的response进行解析:! O# z7 [; r6 Z6 ~, _4 c1 v
1 G9 I7 s! @/ y
html = respone.content.decode('utf-8')+ p. u' Z' @5 f9 {9 R
soup = BeautifulSoup(html, 'lxml')
; \* \6 e$ X" R9 [1
, e- J0 N9 V8 @9 S3 J7 E2) a2 J- U! i- ?" E
以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
! u( i' }8 S7 W, f# Q# 获取head标签
% p* L4 _8 Y3 g8 S! V2 rprint('head标签内容', soup.head)
. L2 r2 M+ @' B! d/ `- f* @# 获取title标签
4 O* Z9 ^% {4 E; kprint('head标签内容', soup.title)8 @7 {9 {9 }) i3 b% A" p! V' x. A
# 获取body里面的img内容
8 \& j& V, h1 ?( }! V# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
* ^: e9 Q6 Q! w! {0 Yprint(soup.body.a.img)
1 Y9 z) d* P: Y! e4 p6 U) d/ b6 Y# 获取所有的img标签 使用find_all()搜索整个soup对象
( p: l8 }- |/ B" \" h8 B# hprint("获取所有的img标签", soup.find_all('img'))* z: ?5 p4 F' p$ w
# 获取标签中的属性src地址
: A. m9 H* o' qprint("获取标签中的属性src地址:", soup.img['src']) # 注意:英文点号都只能获取第一个值
& Q B" I; b8 d7 P- ], e" T1 K1 G N) x
9 g4 {$ Y# f" \# |; h$ e
# 获取soup的name5 z; R' u; N: E
print("获取soup的name:",soup.name)% y; d' H! G* |" g0 G7 i+ f3 }) Y
# 获取a标签名# v& m+ t; {2 o3 @+ E, Y0 @
print("a标签名字:",soup.a.name)
: P J9 M* t" k: I- Y& ~tag = soup.a
6 h9 d" h4 }* G" I: w3 xprint(tag)0 Z' h- Z' J) t( P* t3 P
# 修改操作 a标签改为b标签
9 j0 ?* S0 Z0 m5 d# rtag.name = 'b' # 赋值后<a> </a>变为<b> </b>
% Q7 K0 {. J3 [; N4 E0 y# 输出修改后的内容
& }3 U! V. d8 x G" M$ wprint("输出修改后的内容:",tag)$ o& C( U9 `- Y; w( L
# 获取全部的属性 attrs1 n. ]2 x, [; Z
print("tag对象的全部属性:",tag.attrs) # 只能得到当前标签的属性(不包含下属标签)/ l8 I5 J3 T8 J
6 j9 [* V8 Y# U+ S. J U
# 获取属性的class的值 根据键取值
4 M& A) y8 F" M; m2 {( }* }print("获取属性的class的值:",tag["class"])
0 I' m* C4 }' R' [! R. P6 s# C$ w# f- K
% p' m* }, b# x9 Q0 y2 |8 q' w1 |$ e4 r# L7 r0 _& E6 n- X: J
: i2 Y! R- w, n P5 R: o5 y( G2 T6 y. z+ x- Z6 r9 R
"""针对获取的标签属性可以进行增删改查"""
3 V. ^- j) W8 p; n* o# 修改
: N& a' j! d) C7 N. Q' ktag["class"] = "Logo"
* K5 [8 U. L @2 F/ m& X$ Oprint("tag对象的全部属性:",tag.attrs)
( b1 z4 k" u2 }0 b" X/ h2 Y, f# 输出属性% n4 l7 J7 F9 F% B7 `1 z
print("获取属性的class的值:",tag["class"])4 C+ B4 R z2 S! a M; k1 V8 N
# 新增 属性id 赋值logo$ @; J& \5 W* S& _+ E) o7 V) n
tag['id'] = 'logo'
1 h3 R* A0 X# g" U1 u3 H$ K1 nprint("tag对象的全部属性:",tag.attrs)/ Z. V6 y) n, A1 D N, k! E
# 删除属性7 I. g% U3 ^& T
del tag['class']
" O; W- M' `+ ]/ r" Bprint("tag对象的全部属性:",tag.attrs)- a& i6 f7 P* D) B: i6 P3 c
& _# ]6 M: @/ p1 Z4 C. e
. F7 r+ d3 Q2 n" K
' z, ~, D1 b) e2 u% a: p- \3 s"""针对内容操作 (只针对标签,对属性无效)"""9 z$ i: I) ]' i! e# S
# 获取title标签内容: s" a! i' w# K
tag = soup.title0 t: D0 w7 B/ C
# 获取title字符串! E e. `0 r k2 `5 N. c
print("tag对象所包含的字符串:", tag.string)) Y( @2 q% @9 ~: [; b" {
print("类型:", type(tag.string))1 S0 [; W/ d2 q; V. a- Z
# 替换内容8 K" C% Q4 C/ A+ j; B$ Q0 t# g
tag.string.replace_with("你好"). M, {. M: c5 |% y9 b! t/ ~
print(tag.string)! N, e1 w2 |# }; V3 t C! b! l2 g
# <!-- 学科建设 -->
. V; S0 F6 L! ~5 L* m# 获取注释文本内容/ J0 y S0 d; \% i
markup = '<b><!-- 学科建设 --></c>'
2 d; O s: I* N" Esoup_comment = BeautifulSoup(markup, 'lxml'). b6 {" A, r# `
comment = soup_comment.b.string # 以markup第一个标签作为关键进行搜索" P, X2 [/ D: S6 y L9 y$ u5 n
print("获取注释文本内容:", comment)/ u9 | T7 f( A" _& w! h
# get_text()9 ]" T2 Y A. D
print("title的全部节点:",soup.find_all("title"))
7 N! } r2 n0 a6 Y8 t) \print("title的内容:",soup.title.get_text())4 n6 t6 T1 @' q
"""查找ul元素标签"""! ~! G+ X5 g$ r5 f- n3 q
# class是关键名,匹配时后面必须加下划线_: z% [' _ ^% t; k6 ]. S, Y
# tag = soup.find_all("ul", class_='menu') # 按照css类名完全匹配6 [4 O* h4 O. |, E1 P: o, \$ l
# print(tag): g# y- t! i# W; e) d) b
tag = soup.find_all("ul", id='menu') # 按照css类名完全匹配3 |6 T9 C1 d8 \6 g3 e
print(tag)
6 k4 O8 j& f. V( w9 _# 查找名称为a元素的标签内容# z q) c2 h# u
taga = soup.find_all('a')# R. B6 |8 F, r
for tag in taga:. t. R4 \3 p1 s8 c% F
print("查找名称为a元素的标签内容:", tag.string)3 e2 Q$ H! R. ~+ [
# get 获取属性信息 获取整个页面的img标签图片和src属性值/ i5 r' O" V$ g0 r$ t" w
tagings = soup.find_all('img')
* ^# I( |1 V5 f" t% v6 r4 G, Q$ x" @print(tagings)
) ~. O) E4 O/ q# a( I# 循环输出图片地址- J/ |6 W# ]3 M3 b8 j
for imgsrc in tagings:
' ^$ T# }* }" N; T9 S) N+ L print(url+imgsrc.get('src'))
9 I' H% ?3 d; y
% s4 w/ b; w5 S8 p# W4 R""""属性只能做为参数,所有的操作只能针对标签"""0 i1 M* A1 N9 H
; t; ?" L, m2 U. y6 Q$ j
etree方法:
/ S; V1 ?" Q$ d6 k3 G0 m导入库文件:
0 L3 `. s* m; [# S/ G! `6 U$ A; {' Z/ O1 x' J4 C
from lxml import etree
! l2 ^/ i# p4 W# t6 R* D1 e/ A1/ J0 L) {0 u7 a+ M) V- G" O! h
解析得到的response对象;
7 p3 _- ?( h9 X# c& Q
" L9 o2 y3 m5 X# 设置response的字符集
9 N3 Z7 w+ F; O! P. V2 R0 Xhtml = req.content.decode('utf-8') h. y' M- I4 b& Y1 Y
# 解析对象
) G. D. L% j! v% u5 P8 thtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
* }6 V& J9 r8 {" q0 h- h: F
* ^) d/ u7 _! e# G6 D& w, `$ D( s& s常用的方法:
& [2 V: E6 v5 r- b3 u1 g" h: L1 }9 [2 h3 \
3 I$ z. k, X0 W( P2 o# 定位head节点(元素)' V5 v8 y/ O% l8 r4 Y3 A# v& Q+ U' U
result1 = html.xpath('head')
) z6 j. m" Y' b, Z7 Xprint(result1)6 s; h) P) b; m# X3 \3 L: ~
# 定位title节点1 n* J/ E" R S# X; H9 `1 a. P
result2 = html.xpath('/html/head/title')
& i Z' W4 ]1 Y- a# L! Uprint(result2)
3 K/ G, s% L( f% e+ Q# 搜索节点 title节点7 G8 L% `7 l" U* I; w
result3 = html.xpath('//title')
8 g+ p1 A; r. w. Y) C9 Q$ Dprint(result3). u9 i& |) Z9 H& q$ S' J4 x5 N
# 搜索title内容 text()得到文本信息0 Y/ S" V' y' } @, ^- r6 v. e
result4 = html.xpath("//title/text()")
2 B; X2 r8 ~3 T% zprint(result4)
1 e& R% c/ e/ \' r4 T, u# 搜索div节点/ E9 b1 i+ I: O. v& R" F* Y. o
result5 = html.xpath('//div')% d% b1 ^3 I7 P1 z
print(result5)
6 i5 E% J7 x$ i& S4 ^( R# 搜索div节点 并用class属性定位6 o4 d. y( i* g& _4 z
result6 = html.xpath('//div[@class="news"]')
8 W$ Z2 q" @+ A& X' E2 v4 Oprint(result6)* H: f* o! E: U) R% M5 F
# 搜索div节点 id属性定位& L4 H( }4 ] T. d
result7 = html.xpath('//div[@id="news"]')/ y J' o# y* {2 U* w2 w
print(result7)5 z7 b& v3 L3 j& J, T6 D! S
# 获取列表span信息
9 k; ?) |0 [1 ~; I5 [/ b/ jtext = html.xpath('//div[@class="news"]/a/span/text()')5 O) m5 T+ B, S G' i0 A! W
print(text), Q0 F' c q5 J: Y& ^( H1 |. \# k
3 C6 y, h& a( a/ og、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存8 M; x) m5 j* w# J
保存的方式有很多种:3 ]/ _+ l1 a% i) D. [ Z* ]3 {
1、保存至文件
* l- r R' T* r5 E" F) ]' M$ v$ Tcsv、json、text5 R4 T9 V6 m. [! ^6 }. u
2、保存至数据库
3 i# P; S- B' r l, Y6 HMySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库) 关于数据存储后面再做详细介绍
8 T( M# c& v* k# T- E( U0 R( L; A7 ~6 G: @) z
2 W6 ?$ n3 b5 S7 m. K8 y————————————————& P) A4 T" T1 Z) t
版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。) u# H+ d) T/ [* A
原文链接:https://blog.csdn.net/royallucky/article/details/105930473
. |/ ~; ~. X& |$ d. I% u' D& B
$ ^, l/ a+ x' m8 G; x( m
+ w0 g, P* C8 g8 `) _% m! e |
zan
|