- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 559120 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 173109
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 18
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
' p! M3 L" A! Z" A
: w/ |7 {6 d! M* |$ |- ?2 p
. c9 k$ v' S: o t" \
手把手带你5分钟搞定爬虫(聚焦爬虫)
& k+ `; s0 d8 A5 ^$ P. h
+ i) D: t+ H. l2 j- `爬虫的原理; i, h" a7 j/ Y8 P9 J. k7 a' f
7 b3 ^- I1 h- g+ T对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
3 A8 @2 H, f6 v! U0 o( t9 u把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味& S6 ?. S( ^+ \; V3 f: ]4 i
所以说爬虫分为三部曲:+ W( p7 ^& r6 w! Z- \, \) l% d
1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)/ O; G' Y1 [9 l* k
2、去找到你喜欢的食物的位置(得到目标地址)
0 ?* }! I) n7 \1 _; G; Y6 \3 }3、把食物搬回家去(解析网址,获取数据,存储数据)
4 E e8 a4 \2 ]' E! E它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)# W! P" s1 C! t5 H+ _
a、导入需要的库 requests
2 @, n0 R- n! j+ z6 T1 D7 x) H* X4 K1 G" K0 b
import requests# K3 C2 s6 v i
1% S' j# ?) p' k" B
b、明确你要获取数据的网址(这里以百度网站为例)
6 i% G: ]( _( ]9 \
, X( x1 J8 Z7 N% R& V! N Burl = 'http://www.baidu.com'! M. j, V1 {; ~; r }: s
1
5 t$ v1 H$ z: Tc、创建请求
4 I% o# `6 q3 n5 F/ |3 @2 _- l; s1 s- e. }; C l2 W- a
response = requests.get(url)! H3 w: K. F p$ c1 z
1
8 k; J4 P! u2 M( `d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)- t( Y+ s' I7 v2 ?+ {9 L+ ^) J7 Z
% V% ?' o- @, v0 Q: J; Kprint("状态码:",response.status_code)
7 {2 g+ g4 m2 o2 o# D8 [19 q8 X$ D- |1 V& O
当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
) o2 \- v$ @% ]/ B ae、得到网页源码/ D/ c" c( c8 p0 }# c& m; f) C' _$ i
7 V7 I; u6 N0 J" n# B* ?' K& K+ ?
print("内容:",response.text)
$ ~( u' Q% l2 j9 z1" Q' U, P3 l4 ]% n! \
response.content是response.text的二进制形式
0 k2 ?* B8 Z( c6 d% e; L9 ^7 z" E/ P
至此,一个简单的爬虫请求就算是完成了。; w& j: u5 W e+ z& ?5 M- _3 t
当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
( N* S; Z- v: I7 F5 N! [. h1 l5 N nf、解析网址; e; I. E+ k: `# n% f `6 L0 C
刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
9 n0 r+ k: }) ?; xBeautifulSoup:8 o8 u- S/ R+ R' F8 s: K8 Q% O# q' }
首先导入需要的库文件:
8 `6 L0 r1 d0 c9 f5 O! C& N& F; r+ J! I! K# a: X% |
from bs4 import BeautifulSoup# I; I" E) B* q" j' R R) r
1
O/ W; z) b) e5 O8 Z1 A( V然后对上面请求得到的response进行解析:
+ S) I D: Y# Z
; I7 {0 ^3 c$ O3 @1 w/ |, _( zhtml = respone.content.decode('utf-8')' F0 K: }& m9 C7 t
soup = BeautifulSoup(html, 'lxml')
) \$ @! G7 [( q ], L2 {1. c5 H d! ?# N& @0 _
25 Q/ h' {0 m6 B4 O+ {( c6 t+ `
以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:, r; _ t) w) B) m* f, U8 e5 g
# 获取head标签- j2 i a% j) \8 f% P- ]5 m
print('head标签内容', soup.head)
2 X& F$ b6 [4 a% n6 Q! H, B j# 获取title标签
& o* V, p1 M2 Y& wprint('head标签内容', soup.title). J& [( c6 k: x5 ^" F1 \- M+ B
# 获取body里面的img内容$ F1 h$ I) [* u4 l5 q- `
# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
2 O) f5 f7 S0 k5 r. B. ?print(soup.body.a.img) ( ?1 K* \, C! C& ^$ G
# 获取所有的img标签 使用find_all()搜索整个soup对象
: ]6 C1 h \& }- w/ u, w6 Qprint("获取所有的img标签", soup.find_all('img'))
2 S( x, a1 x3 ~# k* @" {' z7 k3 Y- T# 获取标签中的属性src地址: _# v2 z5 g* s a
print("获取标签中的属性src地址:", soup.img['src']) # 注意:英文点号都只能获取第一个值; J0 d( h. V5 }1 F* e
5 `6 g& R- ~! [9 Q5 k/ C8 }, K8 j* ?) o, I% u9 M, [& E1 G8 T% f
# 获取soup的name
$ Y3 f8 @5 ~0 u$ y% H9 kprint("获取soup的name:",soup.name)
' \, `- ?* {" V+ ^# 获取a标签名
: \4 b1 `5 a6 a1 s8 @$ gprint("a标签名字:",soup.a.name)9 S5 u3 }; Y) j
tag = soup.a! ^; [- e8 h% N. T: F/ T
print(tag)
# W G1 L j2 _9 l* c6 G% F# 修改操作 a标签改为b标签; r6 F# }3 |! U/ f
tag.name = 'b' # 赋值后<a> </a>变为<b> </b>& U8 S) ^, D* T1 y/ A
# 输出修改后的内容
: d4 v8 P3 X) v* E1 ~print("输出修改后的内容:",tag)
b" D, A0 X# W- O3 U6 v% v$ S u# 获取全部的属性 attrs9 y% D( A8 h: n/ g+ z
print("tag对象的全部属性:",tag.attrs) # 只能得到当前标签的属性(不包含下属标签)
* H7 g( ^6 k, N. N. E/ j% Q7 q, }2 C5 g+ A) A% F4 b5 |
# 获取属性的class的值 根据键取值- h ]1 f$ |) K0 A- N" D/ u2 r3 e
print("获取属性的class的值:",tag["class"])+ L7 y5 [' E+ |5 L/ }( z
: u% h" M- ^1 J6 K# r" V
- [ V+ G# m) o$ P1 z
- u9 x3 u, A3 l
& t7 ^2 ~, W' j0 L3 a; C1 V"""针对获取的标签属性可以进行增删改查""". [3 T$ C9 \/ @1 `1 e& _2 o$ d- ^4 N& K
# 修改
2 J7 u- g5 b4 O8 [9 f3 a7 ^tag["class"] = "Logo"7 e7 K) }# Z$ D# u, N: n
print("tag对象的全部属性:",tag.attrs)9 W0 ~. M( f& n; O9 D
# 输出属性
0 M2 d8 J) @# u% S4 C" gprint("获取属性的class的值:",tag["class"]) s) }/ q, X$ }& {
# 新增 属性id 赋值logo3 p5 N, o( f ?
tag['id'] = 'logo'
1 E. n" W2 ^+ |$ p, X* h$ gprint("tag对象的全部属性:",tag.attrs)
, x* |% f' f* N# k$ R3 R6 x# 删除属性
a( b j, d- _; @! l' W/ Hdel tag['class']9 y6 h# O+ T. c9 ^. g
print("tag对象的全部属性:",tag.attrs)' D+ A- L. j/ `; J7 i( Q4 S$ f, m
' Q" ?% w" [# {, s0 `: J
, c/ _8 P ~# b! c' i s: C. z
5 p& _9 {, h; Y% p2 P" E, z+ U
"""针对内容操作 (只针对标签,对属性无效)"""
; ^. c( `5 X. @, P& d& b# 获取title标签内容; C# F8 E! Z8 u7 l7 d& y. b
tag = soup.title
1 K( F6 r F+ }# 获取title字符串7 ~$ ^( ^: ~, f8 X: \
print("tag对象所包含的字符串:", tag.string)
+ N. L8 j6 J [8 nprint("类型:", type(tag.string))
$ K1 H: u" z# ~" j; [6 a1 V* a# 替换内容
& ]4 W# m$ L8 P& ] |) C4 ctag.string.replace_with("你好")$ R2 }: A: `$ g& g6 I
print(tag.string): }: k0 {7 ~, w0 }; ^7 x/ G( g. k
# <!-- 学科建设 -->
$ {) p9 Y0 V3 F/ F# 获取注释文本内容# T) q% p0 S$ o
markup = '<b><!-- 学科建设 --></c>'
1 Y7 g4 N$ ?9 C3 E$ T$ j: p* rsoup_comment = BeautifulSoup(markup, 'lxml')# k/ i( T* P( _/ [
comment = soup_comment.b.string # 以markup第一个标签作为关键进行搜索
1 C1 d0 j& o Oprint("获取注释文本内容:", comment)3 X$ f6 w6 q0 J/ v
# get_text()
# r2 Q6 P% G L" a/ U$ J- pprint("title的全部节点:",soup.find_all("title"))
2 l- K9 D* Q2 D* [print("title的内容:",soup.title.get_text())
3 N7 ^. T9 ?& D"""查找ul元素标签"""
& m2 ]+ ?! C; R ^5 v1 x# class是关键名,匹配时后面必须加下划线_
9 _5 k% ~' `8 u" A$ g. D# tag = soup.find_all("ul", class_='menu') # 按照css类名完全匹配! ?+ K* C* L$ E( u) \& y3 E1 A1 K
# print(tag)
9 F1 s5 }* {, ^: ttag = soup.find_all("ul", id='menu') # 按照css类名完全匹配
/ j0 r# V) A, T+ i7 F2 l1 Pprint(tag)
- h7 I& ]1 U3 u D2 T# 查找名称为a元素的标签内容
" U: @& E/ \4 l7 ~0 O, T# g+ ^/ Ztaga = soup.find_all('a')% H1 Y9 v1 k ?2 m7 m3 j# K& F
for tag in taga:- q4 M: T! O- f8 u/ z2 O/ K8 J
print("查找名称为a元素的标签内容:", tag.string)# m7 R& _: ~- }( K
# get 获取属性信息 获取整个页面的img标签图片和src属性值
- X" c+ K; l( btagings = soup.find_all('img')
$ I5 F4 {" c6 r( R) z8 pprint(tagings)
% M" ` O! E' t7 R; R0 n# 循环输出图片地址; g( J1 N1 B+ J4 I
for imgsrc in tagings:
k u! r- m$ j% T. I& \ print(url+imgsrc.get('src'))! a6 S1 J" e9 r# S4 H8 f5 B& M
, o) m! ^( F+ P e. {3 j
""""属性只能做为参数,所有的操作只能针对标签"""
, t0 s2 @+ s9 k2 s e8 P+ C, Y v% }
etree方法:
8 M6 T; @3 x: L5 k4 p导入库文件:
8 P/ Y$ ^$ B! S" s5 A- Y9 P
6 C; y2 u0 K5 C6 q9 B: \# Ifrom lxml import etree
% v) \. H& x, [8 | O1( A+ w$ { L7 d
解析得到的response对象;! k% t2 `6 R, p& y# M( U
" L8 ~9 k, E3 o1 y+ s8 A
# 设置response的字符集
& J. O- d7 R2 ]1 E! u shtml = req.content.decode('utf-8')
+ S2 {" Q) a2 ^9 M" G9 P# 解析对象
! q0 U% C" X% b4 y' b* f2 u4 k- s1 Ahtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))0 [1 ^3 e( [; I' T, y( |
6 g1 `, G* U b7 w( W5 C0 e常用的方法:" a& H6 H" Q, Y6 O" B
l. A+ c# [; O/ H1 O. y2 w$ m$ a1 e# I, L8 z% m7 Z# C; N
# 定位head节点(元素)/ \; y6 Q/ W5 i$ @
result1 = html.xpath('head')3 @ O+ m+ n% N; y$ ]& g
print(result1)2 d7 v% p+ L/ e$ Z
# 定位title节点
' z% }- x) ^7 t9 Wresult2 = html.xpath('/html/head/title')8 `; \3 ^* ?/ c3 B0 [
print(result2)$ k7 u/ H, e- m9 y% U+ g
# 搜索节点 title节点5 _/ I) t1 X G1 R
result3 = html.xpath('//title')
- M* W! B0 O# {# K; mprint(result3), h4 }- `* @9 H* G5 K0 u. d
# 搜索title内容 text()得到文本信息- v$ m' r5 ?3 B0 ?. J
result4 = html.xpath("//title/text()"). r% n& Q% S3 ?# h
print(result4). g# _# @' J' |% z2 V
# 搜索div节点& ?4 A k2 Y9 v
result5 = html.xpath('//div')
( F; v |+ ~. zprint(result5)
: o/ k) \% t, n3 \ D$ n# 搜索div节点 并用class属性定位9 F6 Q8 ]0 S$ m; E4 @, Z7 i
result6 = html.xpath('//div[@class="news"]')! ?/ W* E! L! O+ z4 M" r- D
print(result6)
4 J8 g% x+ K' @$ H! O: k# 搜索div节点 id属性定位; }, B9 c9 h" S6 M0 B5 y, Q
result7 = html.xpath('//div[@id="news"]')/ k# l& ^0 Q7 A2 K
print(result7)7 ]! R$ G4 P& e/ i
# 获取列表span信息* u: T: q# Z; \8 W
text = html.xpath('//div[@class="news"]/a/span/text()')
/ N9 e. T6 v7 y3 k6 {7 Bprint(text)
5 I0 [7 o; j6 o0 j$ t; M/ D4 I2 g2 P! q& M" S
g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
. u+ {! G- d$ b1 G保存的方式有很多种:( u7 `( a* b( c0 `. t0 v# b
1、保存至文件5 @0 g- M6 V! F' a* B( M
csv、json、text
+ ~6 B4 s5 c% R ]# R! a( Z2、保存至数据库
- l) t' C" {5 N) qMySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库) 关于数据存储后面再做详细介绍% t4 P; m% P; }* K8 s, x
1 d* ?' L9 X/ p. I3 N! Y+ G! i% \# F/ r, o" I8 _) W# K
————————————————
7 J! `' g9 d, z4 t# @: D1 B版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。- y: L- x Q7 W5 `2 r
原文链接:https://blog.csdn.net/royallucky/article/details/105930473( W! ]% J, b1 p3 W9 C
) V9 l' I; i4 d) c5 f* L. O2 a" F. Y" r" m) [9 L" }
|
zan
|