数学建模社区-数学中国
标题: 手把手带你5分钟搞定爬虫(聚焦爬虫) [打印本页]
作者: 杨利霞 时间: 2020-5-5 14:21
标题: 手把手带你5分钟搞定爬虫(聚焦爬虫)
" C: o7 i: i9 X+ f- Z& z2 ~' _2 ^3 Y3 `, e' H4 v0 `7 i
5 s- u/ d' B) A/ N
手把手带你5分钟搞定爬虫(聚焦爬虫)
! Y9 f1 ~! m8 I0 n
, Q$ n7 J" Z/ k+ S: u6 E& L爬虫的原理
" B6 P, V- S# @$ A5 x/ }. \
) o( n, I8 m* d. }, N0 n( p3 Z对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫8 O+ N2 y ]; K. v( E
把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味
- W0 L4 u" L: w" D, a' ~所以说爬虫分为三部曲:) f& |0 c9 E: T
1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)9 w- a3 x3 [+ G
2、去找到你喜欢的食物的位置(得到目标地址): w' I2 H' S& S8 v
3、把食物搬回家去(解析网址,获取数据,存储数据)
- P! @4 Y# e: L3 Q' {/ Z它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
/ U3 q7 r( Z) Fa、导入需要的库 requests+ h9 V: S" P! E
+ V1 e" y4 m" b; R9 d. j0 eimport requests6 ]$ P6 q" H' ?( s. m* E
16 I3 w& P3 k; A% e5 ~7 K5 @& \
b、明确你要获取数据的网址(这里以百度网站为例)
- c8 P4 k$ c" ^3 ~+ ?% ?7 ~* T% ` Q" j1 P L0 a+ ?
url = 'http://www.baidu.com'
: B3 Z8 }. T$ _' O4 k9 H13 _9 q6 n2 M+ d/ t; K9 `6 h( j
c、创建请求. E/ H, X1 u( ]1 c/ q8 V O
0 a# o7 G+ ~. m: O, ?! \ z
response = requests.get(url)
8 _/ U0 j% @5 y% I1, f; ^, K% w2 P! U- {1 S$ I7 J
d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)/ d! u+ D+ p+ e7 V- K( J X
! a7 Z+ }3 P) o
print("状态码:",response.status_code)' d& N9 W" O. l* t' p" ^2 @/ L
19 s! K, ?4 H% t6 R
当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url, L9 l* g+ u, N+ J' Z* N. A j C
e、得到网页源码
+ ]0 e+ n& K" b& h5 X; l
% x% Q$ t7 `2 |" K5 d6 } Dprint("内容:",response.text). g9 y4 r$ ?! H
18 L# G$ V$ G9 Y; Q- A3 A; Z
response.content是response.text的二进制形式% Y3 Q, @3 C+ K3 a# C
, O0 j2 A O0 V2 J, }至此,一个简单的爬虫请求就算是完成了。8 N1 U/ v+ z' `3 w2 q+ u1 u8 [9 F
当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据- l; X# h0 h+ e& x1 G _2 |
f、解析网址; W0 ~2 s7 C$ e* @2 ]
刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
& Y5 k/ F" Z" J o* Q6 wBeautifulSoup:2 {9 E# S/ }0 e9 F G! A5 n
首先导入需要的库文件:- A; X, p8 O4 l6 ^- {$ J
* `4 @& N* K. O, Q0 ~from bs4 import BeautifulSoup( ]9 s8 `2 f7 G% s" M
14 T0 b% T3 d) Z& O2 e
然后对上面请求得到的response进行解析:& T+ X2 n" \2 v1 t. j. s+ _
& ]6 p) D! R& {" l3 X Q5 _1 ehtml = respone.content.decode('utf-8')
. H, l8 @; L% rsoup = BeautifulSoup(html, 'lxml') }) d( G2 N7 S2 s
16 p+ W' X0 B! L
2
+ X7 ?2 T" e5 Q以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
# }- R5 O. k1 @: K9 Z2 n% [# 获取head标签
5 e0 O& {: J% l0 V( M& p5 Fprint('head标签内容', soup.head)
' G- Y: V* i# a4 O# A/ X# w# 获取title标签2 m. e# t, _$ Z4 Z
print('head标签内容', soup.title); `& O! S( W8 Y% y8 B* g7 p9 h( d# Y4 e4 a
# 获取body里面的img内容
/ ]0 e+ M9 \# i9 D+ D4 t# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签), U4 g& `* w( S9 b9 ?
print(soup.body.a.img) 2 a p3 u9 H; ?! ^6 s5 z0 B6 Z" k
# 获取所有的img标签 使用find_all()搜索整个soup对象
7 }: \$ ]/ p, Q9 I) q* Eprint("获取所有的img标签", soup.find_all('img'))8 B1 X D0 D2 {* W/ a" D: M6 Z- c
# 获取标签中的属性src地址, |& O3 N2 o8 d* x; {- j# u- J4 t
print("获取标签中的属性src地址:", soup.img['src']) # 注意:英文点号都只能获取第一个值
/ t. s0 f- z0 F! e) n. G( U' N# j& q: j; s: c* j0 K6 L
- O/ x4 V \7 W, s" ~6 y# 获取soup的name
+ R2 s8 [/ g# G( `! zprint("获取soup的name:",soup.name)8 I9 F7 f& c& ^1 b
# 获取a标签名/ o1 {+ l# s! n+ ^+ A
print("a标签名字:",soup.a.name); b: L7 t$ R7 X1 \
tag = soup.a
k. x+ N. G4 N( a/ ]! Rprint(tag)
6 L9 }" S2 m0 \5 ^" y6 I; c# @' z# 修改操作 a标签改为b标签$ {" i, f, F' T8 {" }
tag.name = 'b' # 赋值后<a> </a>变为<b> </b>2 l7 d% e* F# M- C* ^' r, u8 Z" K
# 输出修改后的内容; V4 K$ a5 W, l4 k
print("输出修改后的内容:",tag)
2 P7 B J5 ]' q f: p6 p5 S3 ~# 获取全部的属性 attrs6 {" i. c- M H6 c7 ~* h+ b
print("tag对象的全部属性:",tag.attrs) # 只能得到当前标签的属性(不包含下属标签)
5 \$ O L- l E7 g0 l. ?2 N+ x9 T6 T, }3 l: D4 R9 \
# 获取属性的class的值 根据键取值
+ o! L2 d; m/ l9 Y" Hprint("获取属性的class的值:",tag["class"])$ I5 l! z6 v6 ^# z
6 D- W% F6 b) ~: C: ~7 E% [& q. K+ c: c
5 G! i ?( i9 I( Y1 f6 Q _5 {
. n7 A1 ]: F Q
"""针对获取的标签属性可以进行增删改查"""4 b3 c1 [( z2 x$ B
# 修改3 _5 N8 p$ K+ h1 t/ {7 J( q
tag["class"] = "Logo"
# t& c1 K0 i6 L% B% B' Uprint("tag对象的全部属性:",tag.attrs)
]9 H9 Z+ f5 a9 K5 G+ {' m2 ]6 s# 输出属性7 I d5 s& n [. H6 ?
print("获取属性的class的值:",tag["class"])
4 a9 u' p9 y1 g' t; ?9 L# 新增 属性id 赋值logo& B* e7 w* K b2 ? b; _
tag['id'] = 'logo'( E8 K# W$ M% \) W
print("tag对象的全部属性:",tag.attrs)" q& T, w3 f" m) o7 I
# 删除属性0 M0 _0 m9 ^0 M5 p" h3 m
del tag['class']
! U: ~4 o( e; p. S5 b9 F; D, Eprint("tag对象的全部属性:",tag.attrs)
n& d; D) c0 l' d% } n3 A/ p. O4 u4 J M
% m0 \) S8 G! o) d+ E' g9 U* U" ?& _5 `( Z0 @ ~! S w
"""针对内容操作 (只针对标签,对属性无效)""": o2 z( }% L2 x$ T/ D6 f
# 获取title标签内容) D: p* J5 L% h) W. j k
tag = soup.title
3 |: D3 y) a& N& K( ~( B# 获取title字符串
& M$ l6 f& w7 O; Jprint("tag对象所包含的字符串:", tag.string)5 M. h) w7 g% `8 ?/ _, l
print("类型:", type(tag.string))
" Z" T3 w: K0 E0 R) v7 g- j7 Q3 m- `# 替换内容
' ]9 i+ W. Y6 Y& y4 }5 jtag.string.replace_with("你好")
. r1 f, l1 e6 ~0 d% Tprint(tag.string)
I4 Z8 a6 q$ p3 J: M( {# <!-- 学科建设 -->
4 L8 o( N0 L" t, s0 w0 |2 G2 V2 \# 获取注释文本内容
1 u7 z; E3 A. g! c0 I Omarkup = '<b><!-- 学科建设 --></c>'5 U D- f% d; } |, _ A6 ?
soup_comment = BeautifulSoup(markup, 'lxml')
1 i. B3 s6 Y+ |2 B* p% S* rcomment = soup_comment.b.string # 以markup第一个标签作为关键进行搜索
) w! ~- W" o. M" n4 z: Y( y( ?, ~) Pprint("获取注释文本内容:", comment)
3 N6 \* j7 h0 E( {- {# get_text()! I% U* ?8 X* v& g
print("title的全部节点:",soup.find_all("title"))# ]1 G, V; N; ]# m
print("title的内容:",soup.title.get_text())
( U5 v( B& m5 b# r4 Y"""查找ul元素标签"""( f9 ^. I7 c5 r+ j. L$ r' N& E
# class是关键名,匹配时后面必须加下划线_( O) ~5 G* x4 W9 I
# tag = soup.find_all("ul", class_='menu') # 按照css类名完全匹配
2 Q8 `5 B: X$ z }* e0 Y* [# print(tag)( p- }1 x* w! I/ B
tag = soup.find_all("ul", id='menu') # 按照css类名完全匹配9 ^1 R( `3 {9 a0 a; X' P
print(tag)
8 ]! N9 x% k+ ^# 查找名称为a元素的标签内容
6 N/ @/ v V5 ~, Ctaga = soup.find_all('a')
$ G+ e; I' [8 a$ y0 E, V' kfor tag in taga:; @4 p9 v$ F% S
print("查找名称为a元素的标签内容:", tag.string)
' J0 g5 I' | Y! R+ ]; A( W# get 获取属性信息 获取整个页面的img标签图片和src属性值$ f( R) S* s4 H) F5 V! R) ]4 w
tagings = soup.find_all('img'), V$ P4 F4 i) m, t$ F* m2 o# S
print(tagings)* G3 z+ t& C* {: A# g* [
# 循环输出图片地址! C2 y0 y+ y9 f& o' ?' _/ S
for imgsrc in tagings:
; F7 ~6 E7 }, Q& V a print(url+imgsrc.get('src'))9 x! a) O" N# Z, ~4 S
; v9 j! M, ^* e$ N+ a- b/ c0 ^""""属性只能做为参数,所有的操作只能针对标签"""
' j, ^- K: h9 t
. n( i/ x- Y+ { w1 Q0 [etree方法:8 c/ Q' t% b( i0 g5 h0 Q+ s
导入库文件:- ]. F0 s1 s$ g, Q6 d' \; ?, ^
" g7 b7 p( D6 |* v* Kfrom lxml import etree6 H$ ], O' U2 D; w7 T6 c
11 ]( r" d% m5 _* q5 {
解析得到的response对象;1 q ?$ p. v) B5 y
$ o: l' _+ x& i
# 设置response的字符集
: F" X8 `: S& n( I& o6 n/ Fhtml = req.content.decode('utf-8')
' ]4 B4 P& w4 ]3 C# 解析对象1 c. h- t4 Q: [
html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))% M9 B$ P5 A5 ~5 N' F A9 D3 d
+ B8 @! F* w/ t5 y1 }# s7 ]7 \
常用的方法:6 G1 F8 a8 t3 H. x
- b% a9 l2 p8 w% ]- X: t1 Q; [3 T& A: @! f& t: D
# 定位head节点(元素)
4 r2 P. q7 N+ N2 R3 ?4 A& Mresult1 = html.xpath('head')
3 I" |6 c" F- C. Mprint(result1)% M- N$ m- |- \' x, H
# 定位title节点
6 t' C/ I. |6 u4 ]result2 = html.xpath('/html/head/title'). G f; U" @1 \# C# i
print(result2)
3 G- ^6 h' H1 z" [: s& O# 搜索节点 title节点$ a3 C4 [. Z. f! F7 R- d
result3 = html.xpath('//title')
) F+ j4 z! e L! i: E: z X0 Rprint(result3): _/ T: c2 Q* b4 u% M9 V
# 搜索title内容 text()得到文本信息
$ t. c3 @; V" p# z9 M: Lresult4 = html.xpath("//title/text()")
6 D4 K4 L/ |. k2 [3 |% H6 fprint(result4)
# g9 ?; a y5 n" T6 h+ m, }# 搜索div节点) j, {8 r0 Z. p6 j
result5 = html.xpath('//div')* J8 w- N( H& V* i- Z! [
print(result5)
F, }0 j* c/ c6 Q# 搜索div节点 并用class属性定位+ Y5 |& C3 Z/ X) P
result6 = html.xpath('//div[@class="news"]')
4 ~! j8 ?* ^4 v2 C; R: sprint(result6): X" t- d) b0 S& y' |
# 搜索div节点 id属性定位
I' t4 e% K) @% U( r% Aresult7 = html.xpath('//div[@id="news"]')9 T4 F, f/ d2 e
print(result7)
. C6 o: g* x; r7 R# 获取列表span信息
% @ d! e0 ]5 I" Otext = html.xpath('//div[@class="news"]/a/span/text()')
1 H5 Y5 u9 e) Rprint(text)
! p5 j9 Q2 C. `5 l, B/ n3 Q/ ?7 d4 J3 \4 L B) G% `
g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存# W0 z% ~9 |' Q1 V9 A- Z
保存的方式有很多种:8 \# f5 ]0 e; {7 e3 F2 J* [- V8 J3 [
1、保存至文件) R. a6 q/ A. G9 P
csv、json、text
5 q8 h* A- P/ I, G2、保存至数据库
, l; C: U& O+ N; Z, ~5 vMySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)
关于数据存储后面再做详细介绍
- ]! g% f% V4 w" F. u/ Q( w5 X! v1 f) }/ l* x( G
$ T3 E# Z4 \: w$ {& l1 C% p
————————————————& @/ c* z! z2 y2 a0 `! N% l$ J
版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
. N' |/ I7 x# o, ?, i4 R" V M原文链接:https://blog.csdn.net/royallucky/article/details/105930473$ W& _* d4 c/ P- Z% T6 w1 z2 [6 d& a
; s: _; ^: s5 F# x3 h! y/ {4 D
! `" M; l9 a' \' j
作者: 建模小白12138 时间: 2020-5-5 20:43
感谢楼主,,,,,,,,,,,,,,。: t! w$ }5 `" f r5 r3 x
| 欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) |
Powered by Discuz! X2.5 |