QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3703|回复: 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
    ; q, b6 H6 E2 o. x
    9 k0 e- G8 ?5 s) y7 F. i+ V

    # z& E- ^9 E. O
    手把手带你5分钟搞定爬虫(聚焦爬虫)

    , z/ x/ J, z+ V
    7 s/ H3 V4 g( |2 p: @爬虫的原理1 L6 A/ c6 h  \9 m, m# s7 m

    & P- b$ f6 e" j9 O" T对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
    ' V$ ?* C8 L2 g& R把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味
    0 J# K1 H# I2 U2 K, |3 G所以说爬虫分为三部曲:! A0 X/ o9 o. O- y
    1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)
    - u5 W5 `) |# h5 }2、去找到你喜欢的食物的位置(得到目标地址)2 a, [  o- I$ [3 U; i4 x2 z
    3、把食物搬回家去(解析网址,获取数据,存储数据)& l/ C$ v1 b5 Y, x7 y8 z; V
    它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)" B% O6 ]( s% Y! Z
    a、导入需要的库 requests% T8 S0 M6 V6 h, x! i6 w+ J% ]

    ' ^- }. ^# }/ g- ?5 `; ^! ?" u* aimport requests- y; K+ A3 _3 n1 D8 f
    1
    5 |& k0 m3 ^% S( O9 ~5 ub、明确你要获取数据的网址(这里以百度网站为例)2 `, K, G( B( V0 |- [
    2 R# I: I9 o0 _, K0 ]) G; k  D
    url = 'http://www.baidu.com'
    4 ~/ y5 b5 g  g( F3 Y1
    7 b; `/ h. J; p* x% ~4 k7 ?) Vc、创建请求
    % j! g7 G& @3 Y5 H2 F+ N9 E
    3 h" K1 q. Y( U5 U2 Q9 lresponse =  requests.get(url)8 g9 J# g  F3 x& Y& ]
    1
    6 N0 h! o, @6 e- `, xd、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)& N8 _2 i( T* D8 N2 ~

    7 @9 {, E' S2 n6 eprint("状态码:",response.status_code)6 q- I) w6 A0 p) L
    1
    & a1 K- q) T& r  I4 G当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
    , i1 F) b, ?4 W) q* Se、得到网页源码
    ) @" }3 u/ _1 ?4 R  k& Z: E, n/ k5 b# {) T
    print("内容:",response.text): }0 ]8 Y# a+ w- K! R9 n
    1
    ( E* X9 v% ^/ K  |response.content是response.text的二进制形式
      Z3 P$ S  G0 q% ^' q* ?0 x
    : ^) `# w) z* z3 `5 W7 n2 @至此,一个简单的爬虫请求就算是完成了。
    ) o. B+ B7 T4 R+ X/ Z" a当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
    9 b0 Z: [. D0 ]; h9 u, a! nf、解析网址
    5 s. @3 x) d8 [% s! ^. D. Z1 x刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)5 v/ `% U, Q. q
    BeautifulSoup:
    ; @0 x. w( X, o* A& k% c首先导入需要的库文件:
    0 t" P' j* @5 q* ^" g% }
    4 K- Y' L7 J- e$ i8 E3 K/ K; Ufrom bs4 import BeautifulSoup
    9 D7 }! f' g0 |& V: u/ a! R1
    : @  \( @0 l: E然后对上面请求得到的response进行解析:
    0 e! m  ~1 o4 y4 R; ~
    : d% o3 D4 J. e. Nhtml = respone.content.decode('utf-8')
    . Y6 L  L! D. B- K& Osoup = BeautifulSoup(html, 'lxml')
    , a, M3 J" _$ ~/ T) X( I7 P+ S) _5 H1
    . M4 Y9 B5 h5 f3 k. x$ }2
    ! a7 g+ v9 j8 W* H以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
    1 g: D5 I/ d; I6 ]7 c  |# 获取head标签
    1 C% J: I! M1 O& Y$ j" _1 {print('head标签内容', soup.head)& c- |6 ]1 j5 v+ s5 ^
    # 获取title标签
    ) g6 D# a1 P+ ^$ ?print('head标签内容', soup.title)
    3 e' L- O1 H) d" X( U# 获取body里面的img内容
    7 s, F% f; R" X5 x% Q4 _' E8 ?% U# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)/ w. f! e+ Z1 W# a9 S; R
    print(soup.body.a.img)   2 \9 g* J3 i# b+ w
    # 获取所有的img标签  使用find_all()搜索整个soup对象
    8 h' i8 D5 \4 r- [& _* z$ Aprint("获取所有的img标签", soup.find_all('img'))7 `" q% W, G4 k4 c  V
    # 获取标签中的属性src地址1 B$ b& U6 ~5 P/ v  B
    print("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值
    ) E5 k% j- ^1 w$ e/ q
    ; ]6 ?' W1 Y" j, E9 f' P9 M- f) Q+ I2 f- O5 ~8 h; I, B
    # 获取soup的name
    8 e3 v& T7 S$ H2 @0 `print("获取soup的name:",soup.name)! p3 l" s: [) [% U' C. U" S
    # 获取a标签名
    ) I! ?6 M# M9 y9 P' G, A3 F6 oprint("a标签名字:",soup.a.name). _) I; A* O0 f' j" k2 z6 q7 h: C
    tag = soup.a: Q" l8 c+ l" C) ?8 @5 h
    print(tag)& Z" _" }* d4 L2 n2 a
    # 修改操作  a标签改为b标签
    $ p, ~1 C$ X4 L# T) P/ f: q  Ztag.name = 'b'   # 赋值后<a> </a>变为<b> </b>( O! [8 Y+ e6 m& E$ u5 ~: s5 C7 ^
    # 输出修改后的内容. P' P. L3 R6 ~3 j0 {+ S% s2 G( _
    print("输出修改后的内容:",tag)* U- }0 K& j. l) ^0 x# b% _8 d/ V
    # 获取全部的属性 attrs/ f: `3 ~' s; X7 J. \
    print("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)
    , o1 B, S+ V: j" p2 L) w* J( l% Y& a8 U# `" \) ?2 z
    # 获取属性的class的值   根据键取值1 H* n0 b3 n; t5 ]0 g
    print("获取属性的class的值:",tag["class"])
    ) F# W" V) q/ b
    3 K; D6 j8 h( n* h4 t/ E% N3 @8 ^5 |& Z! Q0 ?

    . t6 x1 j6 b9 b% t1 m
    7 |; S1 c$ C& M' W0 U% `"""针对获取的标签属性可以进行增删改查"""$ {& T  B) J# ]
    # 修改' e! ^3 Q9 v( p/ N  m
    tag["class"] = "Logo"0 {2 _0 x* o4 w0 F6 y& i
    print("tag对象的全部属性:",tag.attrs)$ h) i  l3 d6 x8 S6 ]
    # 输出属性
    + M& j( `( w0 @& ]- yprint("获取属性的class的值:",tag["class"])5 c( J$ s9 C8 O# ]4 h
    # 新增  属性id  赋值logo
    1 V7 ^% Z' \6 ^9 {' g* v, ytag['id'] = 'logo'
    7 ^0 B8 p- a2 r2 |) _' Oprint("tag对象的全部属性:",tag.attrs)# l9 ]% J; N: ]1 O7 n1 G4 _* w
    # 删除属性5 E0 m( S1 B& J* {, T/ m3 B$ w
    del tag['class']
    * J$ C) D* @) Tprint("tag对象的全部属性:",tag.attrs)  M7 j2 i' L) x; b. N7 I& i
    8 Z( e1 K$ I3 a3 ^% |+ t
    + N0 Q: V# e! J7 |5 w

    + H6 B( m' y) J"""针对内容操作  (只针对标签,对属性无效)"""
    - q8 K1 G0 v" @! M+ D! l3 Q# 获取title标签内容
    6 N* V% c5 p# |6 G( r0 A4 ctag = soup.title; k1 p1 M- |" b# ]; }
    # 获取title字符串  z) q* m3 c  c- K; z
    print("tag对象所包含的字符串:", tag.string)4 J9 X7 @$ ^* w9 z) \
    print("类型:", type(tag.string))" l  V& Z& `2 F9 \) L
    # 替换内容, Z* @7 U( _6 ~* e  o) j
    tag.string.replace_with("你好"), E+ S, F6 V, `& ^3 B
    print(tag.string)% ]) l" v* Y6 A9 O- D& ?
    # <!-- 学科建设 -->
    ( ~2 u! V1 M' f2 Y# 获取注释文本内容/ i/ F& C! U$ g, e% q# t, g) f) O
    markup = '<b><!-- 学科建设 --></c>'% ^" l$ R( O: s. d6 e! Y5 S& ^
    soup_comment = BeautifulSoup(markup, 'lxml')
    $ K! p" w  [. e: R! B: Tcomment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索( r9 \- \7 L* }/ A9 t! m
    print("获取注释文本内容:", comment)
    ; x+ o+ v' W1 @/ |! R# get_text()' `' U7 U' Z/ _! F; r
    print("title的全部节点:",soup.find_all("title"))
    6 v4 \* ]0 U% T$ e$ y. u) oprint("title的内容:",soup.title.get_text())
    6 e9 \. q" C# ]"""查找ul元素标签"""# S: T3 j. @  v1 t( o) l
    # class是关键名,匹配时后面必须加下划线_$ q' q* J7 q! K2 M3 S
    # tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配
    ) T5 e0 a7 i9 v: |+ O' }( _% a# print(tag), D( D; ]9 o  q7 \4 m3 ~9 n
    tag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配; s* F: p0 X5 `1 X# h) g1 w
    print(tag)+ \9 g( {$ c2 P9 k) e9 ~1 w
    # 查找名称为a元素的标签内容; ?$ |+ n& f- P
    taga = soup.find_all('a')/ o/ B1 U6 N- M" `
    for tag in taga:1 z0 e+ {. ]2 I/ f
        print("查找名称为a元素的标签内容:", tag.string)+ Y/ a/ X1 y9 i% k4 v
    # get 获取属性信息  获取整个页面的img标签图片和src属性值
    ) C# M  i6 E& O( o4 ntagings = soup.find_all('img'): S' d8 w( t  w( j$ A- ~  ]
    print(tagings), R  x3 D5 M2 [9 l7 x1 \
    # 循环输出图片地址) D9 [2 a; m% P+ @8 t9 g/ N3 [
    for imgsrc in tagings:
    2 e* S& p2 ]) o" S) V5 O" r    print(url+imgsrc.get('src'))' F( G: g0 R% X/ u, o

    2 K# R" |; S- a; r1 Y9 M""""属性只能做为参数,所有的操作只能针对标签"""" S/ Q: e9 Q1 J2 H
    8 Y! Z4 s6 r3 U: S" e
    etree方法:
    # |( j1 ?; m5 [% G6 k2 }导入库文件:# s& t4 A& v& P# i' F
    0 a4 _" f& g8 ~' q: o+ e3 N% [
    from lxml import etree. i3 L- E5 v7 j. q; u
    1: ~" [4 i6 [( N3 P! R' B+ y
    解析得到的response对象;/ x; C, e: J: y8 g8 g) a
    4 z# O$ R5 E! z
    # 设置response的字符集
    ' f; D( W! z8 M' t) C4 Phtml = req.content.decode('utf-8')9 ]4 Q8 n% K6 {
    # 解析对象6 q/ \- _* w7 A$ I# X) a8 L
    html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
    - C( N0 J" @- T) W2 F- ~. Y
    - ~4 d* X6 x# R) G$ q& V常用的方法:
    $ S: t! N6 M5 P: r& ]# A8 o* x, q2 X, V+ g! X9 Y& S  _

    ' I# t0 b- g* b( l  l  L- h9 B- W# 定位head节点(元素)+ g9 S' }) p2 ]: h$ z$ k0 D+ y
    result1 = html.xpath('head')
    1 O" P  n* }! K1 o0 oprint(result1)! p  ]5 |( u, }! r& q
    # 定位title节点
    ) }0 B9 x& c( O; C7 S0 Mresult2 = html.xpath('/html/head/title')
    ; q0 I& ~$ q# Y+ F$ {/ C; o8 nprint(result2)
    . S1 y5 e9 }$ D# C/ y# 搜索节点  title节点+ k% ~. I. J2 d  }# S. f# N; Z
    result3 = html.xpath('//title')
    ! t" C* W( \5 x* j) A+ r8 fprint(result3)
    2 a; V! U  \+ z) l% W  m# 搜索title内容  text()得到文本信息
    - |, K7 E  ?& {3 u" S% Nresult4 = html.xpath("//title/text()")
    $ K. k  u5 ?& T0 P6 D" I5 Lprint(result4)+ w$ l$ P6 g4 ~( \- e
    # 搜索div节点
    ' Y2 i4 d- w3 }7 a8 Uresult5 = html.xpath('//div')
    $ h9 A" B. Q& kprint(result5)
    & M2 O/ `8 z3 K4 R+ Y6 n# 搜索div节点 并用class属性定位) |  P) j- ?# e
    result6 = html.xpath('//div[@class="news"]')
    ( w# h# }9 ^( o* g$ Hprint(result6)
    ! A* ~, B2 c# ^# o( L# ~/ {# 搜索div节点 id属性定位
    7 @, U) K% |/ u$ z% Cresult7 = html.xpath('//div[@id="news"]')
    $ c, `  b! c5 t# k! o1 cprint(result7)8 t$ Z8 X5 I$ @
    # 获取列表span信息( M1 O- T! K7 ]( {% g
    text = html.xpath('//div[@class="news"]/a/span/text()')
      b" L% T+ s/ b3 P9 A# F+ b; kprint(text)
    : `, H# ]2 |" [
    7 o, h+ T" O6 Q" Y: j* ?+ H" C

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存* z' u; g, ~9 S  ~" W
    保存的方式有很多种:
    * V2 K: J, O7 D' Y* g, d, S# t1、保存至文件! ?0 R( g; I* ~/ Q
    csv、json、text# T# Y! K3 F. L  p9 {: |; o4 b! A
    2、保存至数据库/ z9 f4 [3 T$ B, |2 W
    MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍
    7 z0 {3 I4 ~; e9 D& |# Y; W7 n; D; q" |" Y/ r! ^$ k8 K0 H% G" @
    - Q, `9 c( F$ c3 |9 @! M8 e8 v5 Z
    ————————————————+ ?1 K" g+ A# e0 x$ x+ P/ q8 O
    版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    - F7 H" E* y% n$ f2 b原文链接:https://blog.csdn.net/royallucky/article/details/105930473$ k  ]- b6 l- B/ B  R* e
    ( P2 n, K( t8 c# j2 X: k* a
    ) \/ @7 w" r' b0 {8 c0 I
    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-6-16 18:52 , Processed in 0.436559 second(s), 56 queries .

    回顶部