- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 565784 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174958
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
2 n U3 y; Y& i2 G
$ d, [1 ?9 ]$ i: n9 `
) ]! m6 n" \+ j9 W) m0 R* I+ h手把手带你5分钟搞定爬虫(聚焦爬虫) # K2 ^: i9 Q) K; {, M+ U# U
* K% E0 p8 A0 |爬虫的原理& v6 ]; q7 C6 a5 f+ y1 a& N
8 w3 i) V" \: U6 Q
对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫# Z4 M2 K9 D$ [5 ^( V1 S* J! A
把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味8 X3 z W% ^ U4 w1 F4 Z: Y1 B6 e
所以说爬虫分为三部曲:, m/ F! b1 E8 E! ?( a0 R) Z I
1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)( [2 _$ G8 ~' V/ r& Z8 z
2、去找到你喜欢的食物的位置(得到目标地址)
) d d9 @% k+ A# B! f) i. q& d3、把食物搬回家去(解析网址,获取数据,存储数据)) z$ i1 e# Q8 w/ G( m' T3 _
它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
& a0 T( F H* E: @: J r2 D6 Ma、导入需要的库 requests# ?) ?5 B- b* ^% o, `
9 D/ R+ D$ e# c6 Z7 W0 A4 }5 |
import requests( L5 l( n8 `4 ^' ?" n* _% l
10 @8 Q1 `+ H6 [) b, I- K# A: H
b、明确你要获取数据的网址(这里以百度网站为例)
0 h+ T6 M& D' t
4 L" V2 N6 G, N5 N0 P+ {: aurl = 'http://www.baidu.com'
, P! X6 {: `- U0 R' m- {, q- X+ N1
: \, g6 P" c E! C8 e' Oc、创建请求! O0 y$ h! _* A# u7 X+ ~
# N. W, ?* i- ^response = requests.get(url)
/ w: ?' z! a1 \ @( Y$ n5 [1
- v( x( k! @/ r" wd、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
4 @7 R. w0 U9 Z5 ~ ?9 m4 Q+ G
: H+ d& f. H: E) e- C" bprint("状态码:",response.status_code)
* V) }( m8 P# H& }# e2 i' A1. C" I% ]5 g+ y9 F- k x' }0 e
当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url I9 D' T6 e& f+ ]9 \- E
e、得到网页源码
& h7 D7 i7 O4 c; r- O
$ T. L. w' s m4 k& \9 k8 m6 `print("内容:",response.text)
0 N# K f* ^' A! N2 _7 z! m% \) J1
: w2 J3 n) Z* a" t, \- wresponse.content是response.text的二进制形式
. @7 a: X A! k, \2 w2 b. k4 [# l9 k) h0 O& x- J
至此,一个简单的爬虫请求就算是完成了。
7 J( H* D6 O/ c9 X. s( v当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
2 K* S6 X) I8 Rf、解析网址
, f1 m _8 P, H5 |* }6 k" q5 Y; H刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)3 e# ~7 `; J1 w
BeautifulSoup:' `6 l* T" I) O, `6 J) H
首先导入需要的库文件:8 e4 j$ `, I, H: d7 E4 J8 \ e
$ l9 p( C4 I: F* }. f
from bs4 import BeautifulSoup- d: H; J! n* s
1) a G% g8 p {. U( t
然后对上面请求得到的response进行解析:7 L. X, s1 j/ k$ ?. ?
' s0 p2 N) t8 A# a4 @* g' @! Thtml = respone.content.decode('utf-8'): k1 y$ t# z* T% ~9 S8 d3 @
soup = BeautifulSoup(html, 'lxml')
6 E3 r" n H J* g/ [/ A( S0 E& D1
' ^' X; [$ o& i( k" v* O$ v2) b9 u) I/ s6 p- ?
以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
6 ?; G7 J& z8 y3 `* [1 n7 j# Q# 获取head标签
6 r/ O* C1 P# L: B. N5 Gprint('head标签内容', soup.head)& s- d/ P/ y& I% q0 ?: E
# 获取title标签9 A. |7 S* W/ @* f4 _; p
print('head标签内容', soup.title), a* x- O1 J/ c( E
# 获取body里面的img内容( k5 G8 C* i- _9 b& d3 C: x$ Y
# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)7 {& G1 j# n3 J# ~) |
print(soup.body.a.img) # o q6 U9 y% r& x ~
# 获取所有的img标签 使用find_all()搜索整个soup对象- c R: u1 d- ]% J6 u3 `( `0 Q0 F
print("获取所有的img标签", soup.find_all('img'))3 i' I% g- a, W! M o6 }3 B5 G; N
# 获取标签中的属性src地址+ M1 p$ f# i: z" ?0 W
print("获取标签中的属性src地址:", soup.img['src']) # 注意:英文点号都只能获取第一个值
7 s2 C6 D, M H5 k) U; F* X( ]! O" G/ I3 n4 M
) T# O2 y) A# `' t! P1 @7 m( D# 获取soup的name
+ h( w' ]2 }2 [% lprint("获取soup的name:",soup.name)
m2 s0 M6 ]. \4 Y k9 Y# 获取a标签名8 j# y' H( o7 q2 r( ~
print("a标签名字:",soup.a.name)
8 C- m' [7 I0 Gtag = soup.a
8 U2 b- a- b- n1 I, i- f8 tprint(tag)
, a' m* {1 k- `/ ^ C, Y# H- a2 r. _# 修改操作 a标签改为b标签
$ y) t8 G; W% p/ c% \2 o7 P7 Ctag.name = 'b' # 赋值后<a> </a>变为<b> </b>& }9 |) f, a( g0 W' |2 C
# 输出修改后的内容
0 ^! n0 U( i9 c1 n* S8 I5 n0 v/ @print("输出修改后的内容:",tag)$ D+ m+ X3 K1 A/ `8 ]
# 获取全部的属性 attrs8 t3 G' k" { F. r+ e
print("tag对象的全部属性:",tag.attrs) # 只能得到当前标签的属性(不包含下属标签)* d* C8 h: `, ]
8 K$ w" t( A3 F$ ^! s# 获取属性的class的值 根据键取值4 ]0 U, g o% t# ?6 m" f* c
print("获取属性的class的值:",tag["class"])2 m2 h4 X/ y1 E5 r
+ Z, ]+ B1 f5 J9 P
9 F! R4 {; L- O5 V' Z- U+ H% @- A. Q7 b) X4 z! y( T! N
/ T0 t9 d2 K4 G c
"""针对获取的标签属性可以进行增删改查"""# b+ c: ^8 l3 a7 C% Y/ _
# 修改. F! w* U q G j
tag["class"] = "Logo"( Q3 g5 F+ B) f7 T! ]
print("tag对象的全部属性:",tag.attrs)/ Z2 C2 Z- y2 Z6 p' D8 q
# 输出属性+ ?6 \* X1 K w( Y2 X
print("获取属性的class的值:",tag["class"])* W$ i) a) [+ H" {
# 新增 属性id 赋值logo! t+ W( I Z% @( m
tag['id'] = 'logo' F, [/ f D; J# |9 L. _: S3 i
print("tag对象的全部属性:",tag.attrs)& _! Z. U+ ~# a
# 删除属性
4 ^+ C) L! t: J9 `$ _1 e I6 ndel tag['class']
0 @: |. o7 B; s b. p$ y# }print("tag对象的全部属性:",tag.attrs)" A: b( C$ b$ e
! a5 J( e4 p/ X) k7 d+ P( m" l* \' ]- g: j$ ^, v$ Y
8 L! j- z) k5 I( G" \& E' O5 ["""针对内容操作 (只针对标签,对属性无效)"""
# E8 G( c2 L) k8 p6 u5 w e% w% e# 获取title标签内容3 C [* j4 h2 T) V+ N
tag = soup.title
3 `' K6 {! E0 Q! G e$ n# 获取title字符串
9 s$ S) }! _/ U+ h3 N% w3 zprint("tag对象所包含的字符串:", tag.string)# D9 i$ @5 q# @
print("类型:", type(tag.string))
, x9 D& C8 d8 N% Q2 F# 替换内容
- h2 W/ g8 p! S; n5 Wtag.string.replace_with("你好")4 a: a+ @* h1 Z6 Q; a1 T
print(tag.string)
% L/ O" ?5 _* v# <!-- 学科建设 -->
# x N: d. L" S# H6 ?# 获取注释文本内容
+ F& z5 E& I& _7 |markup = '<b><!-- 学科建设 --></c>'
e! Y. @( \# V7 M* Csoup_comment = BeautifulSoup(markup, 'lxml')
, p2 y3 E- M. a; g' dcomment = soup_comment.b.string # 以markup第一个标签作为关键进行搜索5 `. y% X# r/ b4 N5 U
print("获取注释文本内容:", comment)5 ` n' K- f6 v; @7 ^4 h( G
# get_text()
' P7 w% e- y! q/ vprint("title的全部节点:",soup.find_all("title"))7 T& ]- _6 m5 b0 V; w+ i0 k
print("title的内容:",soup.title.get_text())" E5 d) M% S# ]7 O
"""查找ul元素标签"""+ r' f" ?! k8 ?4 x- A) Z- o% X
# class是关键名,匹配时后面必须加下划线_
' \+ B2 p2 d5 ^5 M# tag = soup.find_all("ul", class_='menu') # 按照css类名完全匹配1 T1 y5 t) _+ K7 J! r6 K
# print(tag)9 [# ]$ {/ ~$ ^; H
tag = soup.find_all("ul", id='menu') # 按照css类名完全匹配
8 h8 w' {6 g! o/ ]) |; r8 c' rprint(tag)4 Q0 f4 z5 l _1 H1 m! X3 r1 ]: `" r: r
# 查找名称为a元素的标签内容0 F+ ~. K" c! n
taga = soup.find_all('a')
# s0 ?3 ~2 _6 m$ U# Mfor tag in taga:' v+ }' P0 E ]4 C7 L
print("查找名称为a元素的标签内容:", tag.string). }% j. |9 u4 s$ _% B" Q1 n9 [% D
# get 获取属性信息 获取整个页面的img标签图片和src属性值. H* t! a% T& Q. n4 Q) p$ e7 ~
tagings = soup.find_all('img')
% A: Z% t/ l% g6 O Qprint(tagings)' K2 J1 e4 h- T: h. v$ E2 A
# 循环输出图片地址: J' g l1 b3 S8 Z
for imgsrc in tagings:
9 g' M: c6 d; }. n; L print(url+imgsrc.get('src'))
4 W( u) | B5 q6 U2 Z: V- g# ]" n3 G) ?' a: h1 B
""""属性只能做为参数,所有的操作只能针对标签"""
+ w7 `2 j# {4 o6 ^5 d, X
0 I7 u2 W0 r; Q8 ?3 j3 E. Getree方法:5 J1 v* s) \0 [$ }1 g, _4 V8 V2 c
导入库文件:
* o7 N, d& \# Q/ w3 e1 L y
; [& `: O; B1 Ifrom lxml import etree
/ Z/ x( i- b( k1
6 w/ p6 [, h9 q1 f3 ~1 f解析得到的response对象;
$ f: `, h s. c6 ~2 a1 U: X1 B2 x, ~( w# Q5 b8 a. b
# 设置response的字符集
! j9 Q5 Q1 `% y6 N+ Fhtml = req.content.decode('utf-8')
1 Q7 w; v# L9 r+ C* m/ ?6 n [# 解析对象8 Q5 n; q b4 d
html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8')), N- F# n" x1 a# G# A9 q* _ d
0 ^7 p; C; l: `! T常用的方法:$ N7 n7 C* v2 D
4 \+ J) c$ N; x# F1 G, Q5 v' h) G: i. X/ C1 ]+ M0 ~
# 定位head节点(元素): n" ?1 x( l3 s" ^+ G2 L/ }5 o7 V; b
result1 = html.xpath('head'): o4 @5 O- c J C
print(result1)
2 N9 I: O4 a" U# 定位title节点
% L/ ?0 N+ l+ Z8 P8 `( v( wresult2 = html.xpath('/html/head/title')! r+ Q# a: ~/ ~* x, B
print(result2)% Q- n# E O" v9 q1 {, b$ v
# 搜索节点 title节点
4 o2 I5 w( ? c* w) iresult3 = html.xpath('//title')
' f9 }; A. f( u2 J2 Zprint(result3)
/ p* z4 h0 r) L* Z+ _0 `# 搜索title内容 text()得到文本信息 T4 I+ K, E, M! ~ i$ i6 H
result4 = html.xpath("//title/text()")- O1 e) V: x2 B2 n5 v( w
print(result4)
* Q3 y& y1 R, m$ q( ]# 搜索div节点2 K% p& c+ n, `3 n& y$ g/ H! O
result5 = html.xpath('//div')+ z4 {9 _. p; T/ @/ c
print(result5)5 n/ _+ o$ a/ s5 x' _
# 搜索div节点 并用class属性定位. k- p& a. X% X, h
result6 = html.xpath('//div[@class="news"]')
, _! a$ A5 v% J! k- A. Kprint(result6)
8 U; w5 ~. X) |6 f& b' P# 搜索div节点 id属性定位
8 P4 `# f: j3 I: {result7 = html.xpath('//div[@id="news"]'), i# r! ]* b; C" j% A# @
print(result7)
" }1 H" B* @& D6 l }& z# 获取列表span信息4 F( M: r$ m: d7 I* a. `( ?4 h
text = html.xpath('//div[@class="news"]/a/span/text()')& _+ d: n; V% d* x% E- k9 Z
print(text)
4 x i r. f7 D
: S( S4 q3 i+ a! D' g7 zg、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
. P2 T+ s; B" ~3 ~2 m4 z保存的方式有很多种:
, h8 a: X$ p" [ e" t9 }( D0 `1、保存至文件 q4 C% X0 v3 p0 L
csv、json、text6 r9 l8 Z! X. H7 ~
2、保存至数据库. |# o/ X4 J* ^- A( L
MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库) 关于数据存储后面再做详细介绍
! Q* E% |: j1 U6 z0 B9 S, _ P
) c- c( l" A3 P0 U8 Z0 J
1 W2 a% w7 h2 X! X; x7 R————————————————- V" o' T8 r! ?+ W
版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。7 ^) c: b2 m' L, D& G
原文链接:https://blog.csdn.net/royallucky/article/details/105930473. ^/ z$ J6 | R4 O8 C1 i
4 \$ k) }7 e6 x$ W/ g, a% [2 O, w- ~" s. H$ `# r! Y8 c, Q
|
zan
|