QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3748|回复: 1
打印 上一主题 下一主题

手把手带你5分钟搞定爬虫(聚焦爬虫)

[复制链接]
字体大小: 正常 放大
杨利霞        

5273

主题

82

听众

17万

积分

  • TA的每日心情
    开心
    2021-8-11 17:59
  • 签到天数: 17 天

    [LV.4]偶尔看看III

    网络挑战赛参赛者

    网络挑战赛参赛者

    自我介绍
    本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。

    群组2018美赛大象算法课程

    群组2018美赛护航培训课程

    群组2019年 数学中国站长建

    群组2019年数据分析师课程

    群组2018年大象老师国赛优

    跳转到指定楼层
    1#
    发表于 2020-5-5 14:21 |只看该作者 |正序浏览
    |招呼Ta 关注Ta
    & Z6 Q* g' F9 K
    , U# i# q: C7 y
    9 f& \" o: t9 `4 D9 u. @
    手把手带你5分钟搞定爬虫(聚焦爬虫)

    2 _0 j( M7 u3 Q- q; F/ v
    0 A# g) V7 i& X" f8 T4 C- V9 I4 a爬虫的原理
    8 M+ `% g7 D( E! @7 r8 d, k0 c  K1 X; L2 @  X
    对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
    ' e3 |4 ?3 T) x; k把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味0 R& r! t5 o' \  I" b$ ~; _* z
    所以说爬虫分为三部曲:
    % e# j/ |" n$ ~3 x2 F5 A* Y6 n1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)
    : x8 L0 U2 c$ `2 _2、去找到你喜欢的食物的位置(得到目标地址)
    , c% U2 o, B6 r/ X8 b' s& t9 A  H3、把食物搬回家去(解析网址,获取数据,存储数据)
    ; n8 Y( u8 e: r) _它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)% S% F4 H6 ]; O5 d) P2 a4 o
    a、导入需要的库 requests" q) a, Y; y7 x+ p" X! a

    4 I" d* X0 {8 n! ~! R/ A7 n6 h: F) mimport requests; F6 R) F1 A* g3 c; k1 X
    1; ]5 b) N, [) V/ o) u
    b、明确你要获取数据的网址(这里以百度网站为例)
    . h& N9 J8 S$ }9 p3 ~  c
    / N  `' \3 x; ^- Furl = 'http://www.baidu.com'. G/ q0 I* T* _& b6 A; }8 N
    1
    5 \, Y4 m# |9 D& |1 Tc、创建请求
    + Y+ k# D3 _9 x! M6 J& S- P4 Y. r: ^9 y( x; S$ M, a& P' T( f
    response =  requests.get(url)
    5 u0 `; h& b! z& a# N1
    ' s3 H, H( z( q/ ?* }* H9 Zd、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
      f3 f2 U8 W0 y$ j2 m* U  g( }9 U+ d" S- c$ \4 k5 S
    print("状态码:",response.status_code)/ ?$ J7 f$ D( k4 R
    1/ {4 K) ~; \- x
    当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
    ) c) P- V# }  g8 k( ue、得到网页源码
    / c* {: s9 x5 t0 c
    ) a3 V" O& A" ?' P; M7 jprint("内容:",response.text)( g) N. S* O5 |, o; [) E
    12 z% p/ _( K% ?7 z! C2 M
    response.content是response.text的二进制形式: F& b- b" P; |+ D8 R* w; E8 `

    - a. ~8 d; p, }: G至此,一个简单的爬虫请求就算是完成了。
    # K& f2 m& W; c0 z( F当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
    ( W' X7 [5 U- d% _. Hf、解析网址( @  a7 k! `) s' j& c
    刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)/ x8 Z. M0 ^& @! I- h
    BeautifulSoup:4 U9 }! ]& S- I- s! P/ {
    首先导入需要的库文件:& O; q0 T/ ?7 s1 B
    9 H* R- s" E, u) f" y" a* y3 Y
    from bs4 import BeautifulSoup: ^& J7 m& }# x: ^4 i& I+ s" x; z
    1
    + m/ @0 I( y) M4 X8 b* O6 M然后对上面请求得到的response进行解析:
    5 Z  P: l! w' @. S9 u! n
    ! u: c/ s" R/ N: C; s3 j+ ^% ~html = respone.content.decode('utf-8'); X8 O* x- @# j6 _
    soup = BeautifulSoup(html, 'lxml')
    # J. ]3 {: N4 Q4 z9 i% f14 k" v4 B  L. |) n0 R* P
    2
    + {# W5 `& \. O. ?以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
    1 I% j# l& V% g0 J7 T* M# 获取head标签. [) L1 y' }! I4 d% G
    print('head标签内容', soup.head)+ j2 S# G, f% c; y, G2 ~. m
    # 获取title标签
    + u3 z( [/ d7 Wprint('head标签内容', soup.title)
    ( B0 ^" O6 C' B0 m# 获取body里面的img内容( |* f9 ]0 _- A" h. G+ g/ X
    # 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)0 V1 d8 t1 O8 p- J- W7 [: u
    print(soup.body.a.img)   7 p* J+ H  B8 Y) i. E  X3 m8 q( \
    # 获取所有的img标签  使用find_all()搜索整个soup对象: m5 s  N# A$ y! j/ _
    print("获取所有的img标签", soup.find_all('img'))9 f2 _: k7 i: F4 j
    # 获取标签中的属性src地址; K  ?$ F8 [! C4 n4 C
    print("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值
    ' j# j) ?# x* u7 I; @
    - _& W4 A$ F  k( a0 O3 s5 u7 E
    4 P. F# Q: J- b! ^2 N9 ~; c/ ^# 获取soup的name  L  y( ]" m# i& Y% ?4 t) X
    print("获取soup的name:",soup.name)
    - L1 A) E( B& N* U- p. Q' T/ q  |/ t# 获取a标签名5 A! p. V. e! }- T8 ]
    print("a标签名字:",soup.a.name)4 {& Q8 J# S/ I) k* U( u& W
    tag = soup.a& e+ \- Q+ p# t! a5 }2 C
    print(tag)2 O" R1 M3 P/ x6 Y! S
    # 修改操作  a标签改为b标签  i' D4 ?! t& y& u! l2 A* g
    tag.name = 'b'   # 赋值后<a> </a>变为<b> </b>
    5 N- f! M2 ?$ p" |/ K# 输出修改后的内容
    ; J, x5 j7 r6 J4 P5 g9 G, e/ Iprint("输出修改后的内容:",tag)
    ' B  X: V( U9 c$ W. B& ]% f" J# 获取全部的属性 attrs
    6 g2 I& {# i; Z4 E+ Eprint("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签). ^. J  R- n: m1 n; j

    ' w$ N: F2 M) u# J% N% ^, K5 b7 l# 获取属性的class的值   根据键取值
    $ u( B  k5 c$ \/ }8 j* _% O2 ^print("获取属性的class的值:",tag["class"])
    ! ~! _, Q; q" _# S& q! m3 ]; ?& \) K5 R9 I& _
    & X' e8 `& t6 n/ h1 u1 u7 f' y

    & {6 {  c3 B4 D7 j% p; |. O. [3 s& @4 M2 ]+ c: p$ q
    """针对获取的标签属性可以进行增删改查"""
    7 v7 I; f2 \  c, r( V! p# 修改% u9 c2 u( Q1 w- G
    tag["class"] = "Logo"+ Y2 d* \+ _( n: E
    print("tag对象的全部属性:",tag.attrs)5 V0 o9 ]5 }+ l! f2 ]5 {, b2 o
    # 输出属性* p5 X  j  R% w# Z- {
    print("获取属性的class的值:",tag["class"])% R% E# V, k/ S* v! [
    # 新增  属性id  赋值logo! v/ @7 ]/ L3 q4 D1 v6 n
    tag['id'] = 'logo'
    ; \+ [# X# W" Aprint("tag对象的全部属性:",tag.attrs)
    : n" J+ ~3 k5 C: ~; p( J# 删除属性
    0 _( E( v/ f1 ~. U! r" o! ddel tag['class']
    7 g+ \7 @) s7 ^4 {8 tprint("tag对象的全部属性:",tag.attrs)) r8 Q9 Y' w2 e/ g! W) u( d
    $ g  J+ U1 f/ q, a1 ?! D

    % }9 G8 y0 n8 P: u' ~3 ^' T- H$ m. C
    ' k& s' n' |+ P1 b! j"""针对内容操作  (只针对标签,对属性无效)"""
    % H+ ]: i( I+ J* Y% z# 获取title标签内容
    ! {% c& i. D0 X7 {" G6 ?tag = soup.title% d; ?$ W3 z! _" s
    # 获取title字符串3 H% K& S  W, \' C( k" i
    print("tag对象所包含的字符串:", tag.string)- S( I1 Q7 E% N/ @! V/ m
    print("类型:", type(tag.string))
    , G. m/ F. }8 @8 v3 F# 替换内容1 ]1 c) d7 t* |0 ?/ K7 x
    tag.string.replace_with("你好")2 E" g0 O" Y5 S% Y0 O
    print(tag.string)6 a7 Q/ r8 i  n
    # <!-- 学科建设 -->
    % R3 r4 w$ q( v8 l# 获取注释文本内容: q$ |: p/ S* s+ W; @- r# [( L& m- g
    markup = '<b><!-- 学科建设 --></c>'
    3 m: f. y% }" {: w# K1 lsoup_comment = BeautifulSoup(markup, 'lxml')
    7 s7 L; K% L- L& f3 kcomment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索
      ]$ ~! @- o! T8 g! y) Jprint("获取注释文本内容:", comment)
    / ?, k. J9 H+ l! }7 I# get_text()
    . a# S' W* ?  S4 b, wprint("title的全部节点:",soup.find_all("title"))( ]& ^, n  r& F2 t5 w1 J
    print("title的内容:",soup.title.get_text())
    ' ?0 Y& Z( l& c; c  V$ Z6 r"""查找ul元素标签"""9 k: c; w+ p! ?/ K% O
    # class是关键名,匹配时后面必须加下划线_
    7 P$ y5 ]5 C+ V" h# tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配
    0 F; X# _" p5 o* E, j4 `# print(tag)
    9 h/ h* @" E' w/ `+ Vtag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配
    ) I: f6 X! X( U/ F7 z5 Fprint(tag)
    : _5 X2 E) P# }5 B0 n' E# 查找名称为a元素的标签内容
    % J) L) K6 ]$ [% u. C. r: ltaga = soup.find_all('a')) o- [- [; d/ S5 l  S& y* R
    for tag in taga:8 v, D4 M* p" U. n, z6 f8 ]
        print("查找名称为a元素的标签内容:", tag.string)* \: X! e' S+ J+ l! O) Q7 c
    # get 获取属性信息  获取整个页面的img标签图片和src属性值
    9 l2 @2 `. J% _% ?3 [3 |0 s1 \tagings = soup.find_all('img')
    % d* {$ f: _1 P3 N0 x- q& @. }print(tagings)$ C6 X; d3 z8 [( H! |
    # 循环输出图片地址
    8 c7 q, A" |  vfor imgsrc in tagings:
    ! _: b0 n7 g# F    print(url+imgsrc.get('src'))
    2 W2 H4 n5 d1 C; Y, K: A0 R. h6 C, n* P# \
    """"属性只能做为参数,所有的操作只能针对标签"""
    : e* t3 h. z2 R- f$ v! l) E! d; X4 }( n' Q% u: F8 ^
    etree方法:
    " ^/ q9 ^! J) R9 i9 R3 _导入库文件:; y% ]7 ~  u+ }4 Z; ^! D0 }
    9 J8 X7 z4 d/ }' M5 y  ~
    from lxml import etree
    " ^8 _0 }# f, T/ ]1/ F: S, x  N0 z; [: E% h
    解析得到的response对象;
    # K. D% I$ j# w  l7 w$ t5 @4 e/ X  I" e
    # 设置response的字符集
    8 a* `: F* |  U2 ]( o& Dhtml = req.content.decode('utf-8')7 F- q& E# J# {3 z* o
    # 解析对象
      X3 L5 X7 @' ~9 Shtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
    7 P( j0 u" b7 h( w# L4 W# `( h8 I8 X4 i% S+ o, x  D1 A8 i3 R' p5 P' U( c
    常用的方法:' n4 L, U4 c4 S4 Y+ u1 H
    * X( [) D" q, l5 s' H* @; K5 F3 F
    , V1 \4 A$ x% h3 w/ ?, z
    # 定位head节点(元素)- ^* H. N; G" L& E3 r! z
    result1 = html.xpath('head')
    , {0 ^, W# [; W- Iprint(result1)
    $ F, j" _. D) f8 k1 Q" A# 定位title节点& ~( C( d% V, ?9 S1 N
    result2 = html.xpath('/html/head/title')
    ' \1 w% F% {6 t) j5 Q# Z# Hprint(result2)3 b$ Q% p9 a! [7 H* x
    # 搜索节点  title节点; q! I5 |- T* ]2 p- w* r
    result3 = html.xpath('//title')5 g; O3 k6 n7 w3 h$ Q% N9 J' n7 l
    print(result3)5 O$ J0 y; w; d- B# Q
    # 搜索title内容  text()得到文本信息9 G& R  L4 W9 W1 J
    result4 = html.xpath("//title/text()")" Y# C7 y9 D0 s- J5 F
    print(result4)6 f' H7 P2 A/ ~9 |9 a
    # 搜索div节点% a& q1 {# A: g5 F; y3 K
    result5 = html.xpath('//div')
    3 m& N9 h4 s" A+ d" bprint(result5)
    5 o8 }  _) b- E6 }; p, Z9 \% ]# 搜索div节点 并用class属性定位
    3 u$ C; L$ j# C3 t  Wresult6 = html.xpath('//div[@class="news"]')+ s9 N7 ~. F* W! U7 j
    print(result6)
    + g) \9 ?  d6 g% Y# 搜索div节点 id属性定位
    ' }) A% b' \% F, B2 Eresult7 = html.xpath('//div[@id="news"]')
    ) N5 ]$ \% q8 H1 b9 y; Lprint(result7)
    9 j! q/ T1 P% V% i# 获取列表span信息- J) g, M) F3 ?% {: `, d( D
    text = html.xpath('//div[@class="news"]/a/span/text()')/ e/ @6 w0 d) B0 N; H  T2 v
    print(text)6 `& V8 g4 q: K+ W

    . ?2 h) d/ ^% K7 @: b0 H2 Q; _

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存$ s; x6 E8 S6 W# l( E5 }
    保存的方式有很多种:3 l3 Z5 C% X! {5 R' d2 O- U
    1、保存至文件
    - q8 l; C2 M7 _1 g4 ]5 }csv、json、text) k! h& p" E) F6 Y' {* I  w
    2、保存至数据库2 q; ]6 c7 F4 G7 Q
    MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍
    & Z5 J8 a0 R0 ]# `6 H
    / U2 R+ P' a8 r5 w/ q+ Y2 \9 C9 w$ G. E& j# B$ z3 Z
    ————————————————
    : ^5 a3 @- M) T版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。9 U; {6 W& _- b2 |; B- V
    原文链接:https://blog.csdn.net/royallucky/article/details/1059304738 F! J* q6 h- A( y/ e) `: c
    ! z) H3 D: `5 ]# @9 ~+ _

    , w" w4 y- `5 X( o4 ^* s
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信

    2

    主题

    5

    听众

    338

    积分

    升级  12.67%

  • TA的每日心情
    奋斗
    2021-7-23 00:47
  • 签到天数: 124 天

    [LV.7]常住居民III

    自我介绍
    Hello world!

    群组2013电工杯A题讨论群组

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-8-5 21:24 , Processed in 0.431768 second(s), 57 queries .

    回顶部