QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3734|回复: 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

    , m$ K. \/ h) D; X

    % r$ g1 {; d/ {
    * g! Z% N) \1 i
    手把手带你5分钟搞定爬虫(聚焦爬虫)
    " n4 x, |4 B; r8 k3 Y/ C% Z) L
    ; c. K  a- _: q: Y5 f! z+ U$ F
    爬虫的原理% q5 q$ Y! r; A" j- }% ^4 G

    + g+ d* [) D7 b$ b对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
    ; Y# K: S% o. p" O) x把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味; D, S4 R+ c, |  u$ o, e  G
    所以说爬虫分为三部曲:
    ' `4 x; c- U; P8 T9 }1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型), i* z- q4 _% m6 T" w2 T
    2、去找到你喜欢的食物的位置(得到目标地址)
      M6 |7 L3 i7 c' O; P) G0 J, J3、把食物搬回家去(解析网址,获取数据,存储数据)
    5 T3 i0 B$ \5 x! ?5 z它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
    + v$ f1 B# Q% G/ y% Oa、导入需要的库 requests
    6 V. J( a' {* t& Y1 }- ~, U% Z- r  H  M$ P: e1 ^; L! W5 v  @
    import requests* ]- k+ G. p4 |# ?7 _
    1
    ' R0 M0 c' m: g% \9 B6 R9 k& [b、明确你要获取数据的网址(这里以百度网站为例)/ N4 v/ g( h" Y+ P+ ]
    & C+ \8 V- d* h4 z
    url = 'http://www.baidu.com'
    - X3 T5 Y5 W  a& V0 l# c0 Y2 H1+ A4 U( I( @  [( n
    c、创建请求
    . M( D/ ^9 T5 f; i
    5 F) r4 `4 u: p3 {$ L7 D( B' H+ @response =  requests.get(url)
    0 k9 p- _  D1 `; @$ n7 t6 H& s# r- e1
    6 Q8 K( B3 ~0 R$ ~6 B, Ed、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)7 g5 V3 j; y3 B- H0 E7 U

      Y7 h, u  m. [: G- s, ]print("状态码:",response.status_code)
      ], f3 z+ @/ {7 K$ Q: O5 b1
    7 u# ~: u3 X" f7 f/ i当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url5 w! a; D1 T" e6 b
    e、得到网页源码; {, O# \  w0 r' F& l

    : _- X7 _+ ?: I6 h8 x7 V& iprint("内容:",response.text)
    $ W3 e2 }2 q2 x  H: y# D2 _$ n$ Z1
    # r; U: Y& [. f- T3 m0 Qresponse.content是response.text的二进制形式
    " g5 T" F$ |0 V! j
    ' ~% Y- }7 J, n$ r) l至此,一个简单的爬虫请求就算是完成了。
    4 l0 m& y( o: z; U+ X当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据! v$ x& ?" O( {, g* _; w- M
    f、解析网址
    . s. c7 k) h. |8 f5 w& I刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)! w, k+ m! h/ |
    BeautifulSoup:
    , a; Z2 b9 v5 @6 W% s首先导入需要的库文件:: t- K4 m+ Y3 V" x
    7 n7 R4 C6 H: i/ b7 M1 q2 \2 ]
    from bs4 import BeautifulSoup& Z$ w7 x) o! O2 O' e5 S* @* F
    1
    " D6 ]: M7 {* S3 T% N2 E" ]然后对上面请求得到的response进行解析:0 F; D- j. s! A5 L2 z( o7 I9 V
    - C/ X( B+ L* B& E, b2 }& d
    html = respone.content.decode('utf-8')- v4 a7 d% \' z2 l  e* u
    soup = BeautifulSoup(html, 'lxml')( v: {* h. J' G# w7 l+ m4 b1 G' J9 G
    1
    5 i: o8 ?9 s$ ]  y* S& j# V; V2
    & J) g$ g# `$ g, N8 {以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:( U  R4 m/ F- i5 u) ?; w1 g  d
    # 获取head标签* \' Q1 b9 R; ~* P& S
    print('head标签内容', soup.head)* N# b+ J' W/ V# \2 @7 M
    # 获取title标签
    8 |3 b9 ~" H2 C! }" nprint('head标签内容', soup.title)2 s4 E7 g/ D3 B3 S# D0 [) ^+ H
    # 获取body里面的img内容
    2 |; v0 P. S3 x' e- f7 w' l. q+ G' Z# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
    7 n( L8 T% f9 Q5 E; |1 Yprint(soup.body.a.img)   8 x! ^% x, Z$ R0 [6 i) M
    # 获取所有的img标签  使用find_all()搜索整个soup对象
    1 Y) z1 s. G6 b( a5 ]7 X, Xprint("获取所有的img标签", soup.find_all('img'))9 d$ G# f: Y8 j/ x+ T+ t+ H: x( G
    # 获取标签中的属性src地址' v) [9 h8 j: D) S4 P
    print("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值
    9 n- P, @  Z$ b; A: x
      T6 p& [$ O5 K, q
    : @6 M1 h' ?* N# 获取soup的name$ g, t1 m$ W0 Z, R
    print("获取soup的name:",soup.name)  p4 R3 X2 c8 ?% a' I7 O
    # 获取a标签名9 K& k9 Q) z( X0 s' N- B8 s$ y. `
    print("a标签名字:",soup.a.name)0 a) b& Q9 o! _. C, n* F3 C3 N7 F
    tag = soup.a
    + z- T1 W+ h, z9 Z0 Gprint(tag)
    ( ~8 g8 I2 {( q  d0 H/ I6 g# 修改操作  a标签改为b标签- o: _, l5 G7 ~) I8 U( R/ V4 Q
    tag.name = 'b'   # 赋值后<a> </a>变为<b> </b># a4 e8 d& y# Z
    # 输出修改后的内容
    2 ~. T' H2 h( g" `% k( m) x2 eprint("输出修改后的内容:",tag)6 V# ?/ w( G7 o, z
    # 获取全部的属性 attrs! @! R/ V8 `; C+ N7 `3 f
    print("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)( c% \' h5 S  |5 b2 ]

    . s/ e/ X( a8 [% _! f; G# 获取属性的class的值   根据键取值
    ! j; H6 Z8 Y& W, Y2 o4 o0 oprint("获取属性的class的值:",tag["class"])
    4 P4 q9 e$ g5 u# N7 H& @( W  ^' M4 M2 H
    ; d1 e8 O9 K- R4 t/ \

    ! P% z  \7 i! I4 J4 N
    " k8 B, ]) {8 O$ G& I& ["""针对获取的标签属性可以进行增删改查"""* j! i8 t; \2 m/ r5 x# u( a( B
    # 修改" l2 ~; e& S8 a. Y6 t+ b7 m% @8 T
    tag["class"] = "Logo"
    7 d4 _% [% Q2 Iprint("tag对象的全部属性:",tag.attrs)
    ' ~4 `; y: ?' w# 输出属性
    " K* H+ R- V; i; o1 o/ M$ G7 Fprint("获取属性的class的值:",tag["class"])# k' N7 z  L1 r3 `5 }
    # 新增  属性id  赋值logo
    , c: ^3 h$ d, A6 f" L( otag['id'] = 'logo'# z  i6 R3 E- ]! d
    print("tag对象的全部属性:",tag.attrs)9 W* {. x8 U6 T* r* [# D0 Y5 I
    # 删除属性
    % f' }0 _: D# {) bdel tag['class']
    % c& I( A# P' s- f0 J! [' ]print("tag对象的全部属性:",tag.attrs)
      p% X2 H' K/ T* ^) O. c/ Y* u. x) L5 f  `5 \

    % b% O9 a! }# _  n3 ^4 F& z3 v4 U
    """针对内容操作  (只针对标签,对属性无效)"""! }5 N8 w9 Z- O, j7 W* J( V% b
    # 获取title标签内容4 O( }# H: A# d9 q# _
    tag = soup.title
    : I* i6 N0 v1 |9 P) E" W9 Q4 f# 获取title字符串/ |( |( ~# u* e, M7 R9 @7 I  Q
    print("tag对象所包含的字符串:", tag.string)
    3 `2 Z, \7 K5 p/ c8 Cprint("类型:", type(tag.string))! s. L- G1 w7 A: f% \( I
    # 替换内容! m2 m# E. Z# _; Y/ P; i
    tag.string.replace_with("你好")
      @  {8 X% p) _, F: Q& r# sprint(tag.string). k! O6 e3 [6 N" G
    # <!-- 学科建设 -->
    * o& ^8 _5 p4 p8 N# 获取注释文本内容8 ~& {1 d/ y7 n1 n# L( t* S, m
    markup = '<b><!-- 学科建设 --></c>'
    " x" o% c* O. U# s+ O  Lsoup_comment = BeautifulSoup(markup, 'lxml'); G% E! E8 ]9 z6 y9 A
    comment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索
    ; j1 }5 g3 I4 A: y3 oprint("获取注释文本内容:", comment)% Y9 C" _$ D% h% k! r
    # get_text()
    6 P3 m2 J& j8 u% @, t9 _print("title的全部节点:",soup.find_all("title"))
    ' F* ?7 n% ~4 t4 V- eprint("title的内容:",soup.title.get_text())
    " H( ]# m0 n0 |0 K# v; }"""查找ul元素标签"""
    + L6 f# A" u' [' D; D$ ^& p# class是关键名,匹配时后面必须加下划线_* ?- p4 A$ x- p4 M
    # tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配
    1 Q! f5 P& X: g+ z# print(tag)
    # ^. \7 s+ l5 b% M2 |$ ]: vtag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配; v! L) R  P2 l/ @
    print(tag)
    - l9 A( e( {, [2 K# 查找名称为a元素的标签内容
    2 Y* U' Y# Z0 P1 U3 \! ]3 [taga = soup.find_all('a'), e: z+ G  c% i
    for tag in taga:
    0 v0 ^5 P; k& N/ q3 s8 m    print("查找名称为a元素的标签内容:", tag.string)
    ( a2 F+ t1 n1 e5 Q: d# get 获取属性信息  获取整个页面的img标签图片和src属性值
    $ W0 `, w% a( V$ {% Vtagings = soup.find_all('img')
    # u( b& t" M" r/ ]' H9 rprint(tagings)
    / O+ K5 G6 u7 W& Z" ?# 循环输出图片地址
    % D6 ?" e: i! p/ M# d! y2 Jfor imgsrc in tagings:; o) A& z1 Y0 p/ a! ], N
        print(url+imgsrc.get('src'))
    $ H" K( z+ Q8 g9 ?
    9 @4 J# [- c0 @. m""""属性只能做为参数,所有的操作只能针对标签""". m  M) W6 @1 B
    0 b1 \  h0 W# Y% e* m
    etree方法:1 n, p8 e6 c4 @4 n: Q3 Q, v5 |
    导入库文件:6 a0 E1 y$ \- Z2 u7 \) F  W

    4 X  I$ _6 v, C3 P8 {& V+ bfrom lxml import etree: L1 E. b& r  P0 g. U/ [9 E
    1
    / v; N" Q! u$ C( M8 z解析得到的response对象;
    " k! B  X5 Z* T8 t( S# C: b, k" U! X. t9 E$ z& R
    # 设置response的字符集
    2 N7 d' R+ |* b- Z- x/ Y3 ~html = req.content.decode('utf-8')% G6 t# A: E1 x' B; T8 m/ Y" L! Z
    # 解析对象% F6 M1 \. v+ ~+ U; E
    html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))0 r3 y' N; }" f) f/ c) d* v
    4 f* M& o  Z; p4 X; o) c7 S
    常用的方法:) o& c1 T3 @9 r( `4 {$ T7 n
    : |% f, S2 \* m" o
      W3 A0 x  {# t& j% _) l
    # 定位head节点(元素)4 Z# B7 l3 B' i, w2 J: v
    result1 = html.xpath('head')+ z8 l: B% B: V3 @3 U: f/ c% m
    print(result1)
    ) b! D9 F- h. a# D# 定位title节点
    9 k: q; \: K+ D$ P2 i* l8 }result2 = html.xpath('/html/head/title')( P0 l( p6 O* A/ z& S
    print(result2)
    ( G# s) U6 H8 @) J; n# 搜索节点  title节点
    ' F4 K) Q# B# w1 F3 q) P3 S8 @result3 = html.xpath('//title')
    3 X" [" b2 W' O9 G- m( r+ zprint(result3)( z: _! }& N+ I5 s, n' E
    # 搜索title内容  text()得到文本信息$ U- M; C$ [. G( D
    result4 = html.xpath("//title/text()")3 z: j, u9 a4 @1 e2 y% {' o( E: z
    print(result4)2 ^, O, E9 V' d' R5 q# C# _) X% M
    # 搜索div节点6 T' [- W- F' |( O3 w; O
    result5 = html.xpath('//div')5 Z1 k& l4 ?! G3 B" C
    print(result5)
    ; V  v& c3 E: \: }8 `" {# 搜索div节点 并用class属性定位7 o) E' U# x  c& b, R4 s( O# w
    result6 = html.xpath('//div[@class="news"]')$ [# i3 M  m- R! z* \9 |
    print(result6)
    * x. A7 k" g9 e9 D# 搜索div节点 id属性定位
    1 B! C" O, J2 l5 m( s! Q4 _; e# cresult7 = html.xpath('//div[@id="news"]')7 D/ Z/ }, Z1 J' Y
    print(result7): r) J* n% r4 B/ U! t
    # 获取列表span信息! i2 \2 B4 s- X) f
    text = html.xpath('//div[@class="news"]/a/span/text()')6 X+ h0 @4 a0 I  V  k: ^  a: w4 t% U
    print(text)
    0 Q) O" A3 V5 a  V) S0 d5 f" W% M
    " [( C1 y$ {/ U: h* X

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
    ( M& l; V1 f! O7 j, K! f/ U, Q" A保存的方式有很多种:
    8 L6 J2 h2 t3 T& ^7 K1 {% k/ D7 Z+ X# A1、保存至文件1 u  X+ y- T" H$ T7 w7 M7 T
    csv、json、text' p& i- w( O0 A, b+ ^4 @
    2、保存至数据库8 w7 y- l  U! K8 h( I- H4 \+ z
    MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍
    - j& A/ n; U0 e& ~5 o' I0 m0 K3 `+ [6 \* w( v& N) J

    - F5 u( j' q( _————————————————
    6 M3 A1 r- B+ l9 ?版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    + R8 X; B$ Z- u& |% C原文链接:https://blog.csdn.net/royallucky/article/details/105930473; b1 u7 ~7 F* I3 c# i) V( q
    * _' J5 A+ d0 j7 @
    + C$ T8 Y3 }! u
    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-7-29 08:22 , Processed in 0.457468 second(s), 55 queries .

    回顶部