QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3700|回复: 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
    / E) B- u3 \' z6 k+ ^
    + k& q1 S2 e; K
    ' }: p* e0 B7 W- b% {
    手把手带你5分钟搞定爬虫(聚焦爬虫)

    1 o" |; J, b- ^+ Z
    3 i, u" F- O1 p* w# I  Q9 q' ^& |. H爬虫的原理
    " j! C* m" s* a* T5 [& t  X% _, f5 f. e7 k) D: l
    对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫$ ^2 C! U# T! W! j7 r
    把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味1 u- y' L& ?" l. y; ^7 l  N& N
    所以说爬虫分为三部曲:) y  J. I% O8 r/ k: j
    1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)
    . Q% J& S2 C( ?# h' @2、去找到你喜欢的食物的位置(得到目标地址)! J' a; z! H8 `; ~5 `6 b/ W! X
    3、把食物搬回家去(解析网址,获取数据,存储数据)
    / o' B3 [( T$ r6 |8 b' G8 S9 }它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
    7 P; b% F3 W- R& S6 z4 W% I$ |a、导入需要的库 requests
    0 v: u6 j5 j$ i  ?3 j% D/ N. O/ z0 ^* B. G5 w6 q7 H% c
    import requests* B1 f1 l. l' H: L
    1- R" |2 g* d7 E& Z' D6 o
    b、明确你要获取数据的网址(这里以百度网站为例)+ B0 Y! y- g6 d8 m8 i5 _
    1 N$ B0 F0 ]. b1 T$ n: u4 U9 b
    url = 'http://www.baidu.com'  a3 m; s" z2 ?  X9 C
    1
    9 a* L' ?; P- Gc、创建请求4 c8 {- v- i! y/ g' T  Z

    3 [* }2 N- a, vresponse =  requests.get(url)
    ) l5 d3 o* l, S* {1 k7 t( A& e1- j' x# H8 a) y4 p  T, P" V3 }$ h5 W
    d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)/ B, u/ a( Y6 K
    1 X! ^6 n# a  S3 p& u8 P1 O( o
    print("状态码:",response.status_code)' g7 X; z# r8 x; @
    1# A) V! B* N% K0 N& d
    当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
    . p4 S; q$ F  S. E$ U% je、得到网页源码9 O* \# I: X+ N
    , w4 V7 q* z6 k3 }1 K% P8 z
    print("内容:",response.text), c& J9 g8 _) q: H" Y. l/ g
    1. p* f- F# u4 N# Q" x
    response.content是response.text的二进制形式
    0 N7 E. ?8 [# ]0 o2 k  |& B' {
    1 g* g) n% X5 M至此,一个简单的爬虫请求就算是完成了。
    $ \0 X5 [$ ^' s6 e当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
    0 a* F) l" T5 ~f、解析网址
    " Y6 n9 \' F- ?" @1 K  D2 o刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)  e/ \% b# [- V6 O& d: j
    BeautifulSoup:; W7 g! A% t+ W, L0 G: b1 q
    首先导入需要的库文件:1 q0 t7 I% \' s" H

    . i- k( W0 G6 t- Jfrom bs4 import BeautifulSoup/ a. L% |  A5 \  x5 x' u
    1
    4 r6 \6 M8 r7 ^0 j/ K+ b然后对上面请求得到的response进行解析:
    . R% H9 K" k) N0 r' N
    " J: g, N# I( G3 |html = respone.content.decode('utf-8')) x* _# A+ u# }. t
    soup = BeautifulSoup(html, 'lxml'), p' l- G( ?- [. X7 d7 m/ P6 V
    1% A! T7 D% {. C2 u1 }) Z
    2. ^2 G+ V+ U# S& ^' m, O2 I
    以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:, F) U; W9 b1 V, M2 k: w+ G
    # 获取head标签+ ^8 s7 O% Z2 _: t
    print('head标签内容', soup.head)6 g( x' g: X( d% l1 n+ T+ Y3 E* Z
    # 获取title标签, s. S$ y; G+ \0 R' L
    print('head标签内容', soup.title)( m2 t1 ~# c; f( R; B. t8 `3 V
    # 获取body里面的img内容" Z8 i* U: |* z2 E2 g
    # 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
    : w7 X) Y/ B( p; [2 r$ [. P4 |* mprint(soup.body.a.img)   + \7 g3 W6 F. }. n/ Q
    # 获取所有的img标签  使用find_all()搜索整个soup对象4 O0 S! [6 t5 |( a1 f
    print("获取所有的img标签", soup.find_all('img'))# j% `. M) c* N
    # 获取标签中的属性src地址# G; ]/ L: _, e% M) }; Y
    print("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值
    & ]7 N6 D# V% E4 S0 V1 v2 k- c% _, Y9 {$ u9 j. q0 s

    6 q* a; N" x5 Z! m1 b# 获取soup的name% g3 m( M! z. Z% E  K3 l% y  O
    print("获取soup的name:",soup.name); [: C7 k: o9 K' {7 q2 ^0 x
    # 获取a标签名
    " q% h1 N/ Y& o# g. Dprint("a标签名字:",soup.a.name)
    # }5 R4 s' c0 U7 O& ftag = soup.a% ]/ W) g: d6 i  v
    print(tag)2 @6 i  f& U* a3 M+ _( `; t
    # 修改操作  a标签改为b标签1 k! }; [( k, g9 K
    tag.name = 'b'   # 赋值后<a> </a>变为<b> </b>. r) [# _2 B6 c' A3 W
    # 输出修改后的内容! s- U# H# I" S+ u7 F- C
    print("输出修改后的内容:",tag)
    * n( o) b! I: b) v9 c# 获取全部的属性 attrs
    9 p: U5 P. v+ M& {9 _print("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)
    " Y' s. ~/ S) p$ p
    5 a0 f! e& q! e# F' a# 获取属性的class的值   根据键取值
    . |$ d. D3 Q% \. ~$ dprint("获取属性的class的值:",tag["class"])  Y" Q/ b' }6 w7 ~+ g  e$ O
    : N& W& c; M% M2 `

    ) |% I- I, d+ S7 u- c; ^
    7 P2 C# L( v! \( O: g( {, z- Z$ G) c7 a* T5 A+ s
    """针对获取的标签属性可以进行增删改查"""
    7 A; t7 |" c6 h+ n* e8 N) w: ]# 修改
    " h* E* M. L* @tag["class"] = "Logo"% R& h$ k, V4 A( S& t
    print("tag对象的全部属性:",tag.attrs)
    4 H5 ^8 w/ O3 y' y( {* B) ^  s! W# 输出属性
    , M, ~# A" Q+ E0 K5 N4 B8 J& |0 Oprint("获取属性的class的值:",tag["class"])
    6 u0 N0 i0 Q9 V( ^# 新增  属性id  赋值logo
    ( x% S2 y, ~7 K, ^; s% m! ]  C4 itag['id'] = 'logo'& A3 ~: A6 Z, M, z- `
    print("tag对象的全部属性:",tag.attrs)8 X- \" B( C* X5 k
    # 删除属性, S1 }. t) L' _/ k( T' A
    del tag['class']5 z% D5 ]. E2 B( Q6 b7 h4 X& V- D
    print("tag对象的全部属性:",tag.attrs): }# M) y* a* h7 ^! d* D
    * f0 i" ?! t0 Z3 z2 s- w

    & W( B8 T* G% f- p. S* `3 l3 E" |1 L1 n6 H- ?1 C  ~: z( r# Q
    """针对内容操作  (只针对标签,对属性无效)"""
    ! c; e/ F6 O- i3 A% t# 获取title标签内容$ b* h( s3 Q0 P0 A0 P9 {0 l, h6 ]
    tag = soup.title2 p5 N) w9 ]% ?. g1 W, V8 P
    # 获取title字符串
    4 f. b; ^- ]3 I+ |; c* iprint("tag对象所包含的字符串:", tag.string), C* O; u; f  G& Q) l
    print("类型:", type(tag.string))
    4 |9 U3 l8 D5 Z* _# 替换内容
    : N4 v0 t7 s( m4 Otag.string.replace_with("你好")4 O' p: N& d, S7 _% z5 o
    print(tag.string)
    , L$ @! ~, m6 ]# <!-- 学科建设 -->! {; D; N$ k! P" }
    # 获取注释文本内容
    , e- r& Y4 P( m+ p2 X1 `' \markup = '<b><!-- 学科建设 --></c>'
    ' |! m) E3 q4 S" |$ }6 Ysoup_comment = BeautifulSoup(markup, 'lxml')3 d$ M  N; u+ B) ~9 _9 V
    comment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索
    ! T  i9 C7 m/ q& v, `print("获取注释文本内容:", comment)% }, q7 F7 t6 m
    # get_text()4 ?; u) O  [5 s+ q. q
    print("title的全部节点:",soup.find_all("title"))0 r5 V" ?6 k  |& _1 v- G
    print("title的内容:",soup.title.get_text())
    & h4 v& c' A6 x( i  ^* n"""查找ul元素标签"""0 F5 L9 U; H3 _/ j! W
    # class是关键名,匹配时后面必须加下划线_2 s* R1 s7 m, C3 H3 Q' z, v- x
    # tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配
    8 _2 z1 i9 ?" q* m2 W+ K+ h& v8 m# print(tag)
    / H) d) E( ?; y% X0 O" P6 ltag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配0 W! I; _' a0 ?5 X/ i/ P! ~
    print(tag)
    9 E% K  w8 u$ s$ D# 查找名称为a元素的标签内容
    # S3 J& i# t1 I! s$ Etaga = soup.find_all('a')1 g% D; s. L' F. r
    for tag in taga:
    - d( ]6 M% E. q: |    print("查找名称为a元素的标签内容:", tag.string)1 {9 x7 Q# N: c- O0 i
    # get 获取属性信息  获取整个页面的img标签图片和src属性值
    * V& T6 x: O9 j$ s3 Y3 l1 ltagings = soup.find_all('img')
    / v' P9 [9 K% |5 |print(tagings)) b) J3 o+ q4 n  n+ T
    # 循环输出图片地址
    : ?( C% p% I( ?$ x* R, }1 gfor imgsrc in tagings:
      N. B2 s  z! G' u8 u! Z2 `- U    print(url+imgsrc.get('src')). I( X3 B- Q* x; Y8 j
    % u! L' U1 n% m- L2 R
    """"属性只能做为参数,所有的操作只能针对标签"""0 E9 e9 Z# q$ E  U% z1 F3 a+ u
    0 I4 h7 {. U7 k+ S0 d3 V# M$ u
    etree方法:% V2 X3 d+ B- |' Y2 s% J" q
    导入库文件:
    2 T! j; p2 D# D8 Q( l
    , l, a$ s1 Q" y+ a( d2 Pfrom lxml import etree9 d0 d1 ]' N) U- H( g- G1 }
    1
    6 r, N# y& z6 e2 Z( k9 q解析得到的response对象;
      }5 u" [7 f+ u1 G4 @) E0 A& ~+ F( R) J
    # 设置response的字符集
    ! u- W2 w* a6 v- X* [% _html = req.content.decode('utf-8')1 r7 W8 M$ @9 U4 ~8 G
    # 解析对象
    4 n/ G8 I+ l+ f& Qhtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
    . v& J5 j  |2 o6 y, ]5 M. s; p* L" `
    # z6 d5 d- t6 g6 [常用的方法:7 W# J$ v. i1 ~, s) }% D! U: s& V' n

    6 l- g: H) R* c; [- W- K( a2 l( z# B$ V" ^# m" A2 {
    # 定位head节点(元素)  H8 F5 o+ r0 h: q
    result1 = html.xpath('head'). e. E0 U* d6 v1 b
    print(result1)
    1 K$ h7 X* I# N# 定位title节点; p# h9 P5 E, u2 F3 f" H
    result2 = html.xpath('/html/head/title')
    ' C/ f2 u5 \' j1 z; A' B7 U9 z) gprint(result2)  u0 r4 i9 n4 @
    # 搜索节点  title节点1 @9 O, q; t# ~) _/ b- ~# i
    result3 = html.xpath('//title')
    / s3 Q6 G* T% m! L) B0 m$ ]print(result3)! q5 z5 A- O% q3 W; e% u
    # 搜索title内容  text()得到文本信息
    - K8 f% w/ v: m3 aresult4 = html.xpath("//title/text()")  |: r- K( n6 ?& |1 \8 t
    print(result4)2 e( c0 Q, v' |+ L0 v/ X2 `( j
    # 搜索div节点
    5 t; o; n9 [4 T; x" a& Eresult5 = html.xpath('//div')+ c% A) B' u* D/ S/ ~$ r2 @  \2 j! R
    print(result5)$ b! v6 `" g8 \) x  }5 }/ j: Y. u" h
    # 搜索div节点 并用class属性定位$ g1 E! B5 }! g4 f# H9 ?; ]. F
    result6 = html.xpath('//div[@class="news"]')# ~, V; Z8 M: K; T+ |) s6 g
    print(result6)  U0 Y! j. C5 c/ m& X! W
    # 搜索div节点 id属性定位
    ! l, y9 b8 c7 \result7 = html.xpath('//div[@id="news"]')
    , B* v8 C+ R! }/ O8 S( F5 ~5 Lprint(result7)
    ) P' Q3 M9 h: B! U( N& h! y/ \  D: _# 获取列表span信息8 {( ^2 o4 ^3 S( x  G7 K
    text = html.xpath('//div[@class="news"]/a/span/text()')
    ; Q! Q* p4 O; ?. O6 a4 O; W. Oprint(text)
    8 i/ H) A) r& U. H/ J, M; \; k1 m& ]$ M1 O

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
    ! M% X; x1 d# I' J7 S7 D7 e* }保存的方式有很多种:
    1 b9 Q6 \+ N; ^1 S& E! h. g1、保存至文件
    3 T5 _; _( E: {csv、json、text
    6 e+ s5 B6 E! t/ D: R2、保存至数据库) F5 b% A9 K% V3 c9 S9 v8 E$ @
    MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍$ }0 U$ o+ ]; O- P

    % Q9 Z: z* p& h5 @/ d4 K( C
    , m+ f* r" ?" o  a1 i, _# I( Y* I————————————————& j( V, Q1 d$ [* L; z1 d0 r- j
    版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。- m$ y6 E! e+ T2 [. S' m
    原文链接:https://blog.csdn.net/royallucky/article/details/1059304739 b2 e& S$ L1 Y1 F1 u+ O; \2 e5 ?
    , G' y+ O$ g8 D8 V; H1 u6 l- T. ~: w. C

    * h3 S9 h9 }6 f& w" x2 K
    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-15 06:30 , Processed in 0.614938 second(s), 56 queries .

    回顶部