QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3658|回复: 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
    9 g$ p# D- L% ]$ _. ~

    . G  R3 u9 y& F3 p
    / }: q& C- y$ W' [$ u
    手把手带你5分钟搞定爬虫(聚焦爬虫)

    9 A+ |* }. @: V: j
    ; S& f. W( e4 \7 K# \爬虫的原理
    & r! r; L. X! x$ Y5 B7 M( I0 O/ d; u+ k0 Z" t5 n
    对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
    * ^5 a# k" w/ Y把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味
    ) A& W( t2 v( b/ c! R! S5 k所以说爬虫分为三部曲:
      I6 b7 R/ J3 f1 ]8 y; n& \4 W1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)! F6 C) a) b0 W' O3 B+ r; R
    2、去找到你喜欢的食物的位置(得到目标地址)
    . J& ~( [! M0 ^. C9 o  _3、把食物搬回家去(解析网址,获取数据,存储数据)
    7 x- M, [' X6 g, W: y; e. N2 J+ e. [6 S它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)2 t; ~( F; X3 D, v- Z
    a、导入需要的库 requests
    5 l& O; J0 L& n1 G' Y; A% B' n3 Y+ O6 f! ]7 l2 k6 h2 o
    import requests$ i2 H: G* i' \$ S) A& F' V
    1
    % Q$ _1 c! s& d4 Y: pb、明确你要获取数据的网址(这里以百度网站为例)
    4 o. D5 {# c% z" Z: w7 }/ H4 [4 C
    7 ^1 [: d3 r$ b! r! O  durl = 'http://www.baidu.com') m/ r6 h, {. h8 A% n
    1  e' Y- x0 I) }& p/ k3 a, U8 A
    c、创建请求
    ; I5 r) z! x- e$ A# x
    & ^5 D; s6 o* w5 Jresponse =  requests.get(url)
      l& Z4 [! B' G/ f& B4 W- ^* z% n$ I& {* `1% R. F6 B  i' W
    d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
    * J7 I: |" _& z6 }8 N. G1 X- {: z4 I4 I* O; g; `% Z' {0 [6 h" h
    print("状态码:",response.status_code)
    / z- e  F5 [3 Q, |5 T5 ?1
      v" s  R2 Q; Q. G4 g% A/ v3 g当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
    $ K6 T8 G5 P/ D) se、得到网页源码
    + I4 C! \# @1 s# p) j
    ' ]5 d5 j, [4 ?5 J9 x& ?print("内容:",response.text)$ }) g$ a. r/ v0 G  g. T& A. Y. M. I
    1
    8 o( w5 H! e! K# {response.content是response.text的二进制形式1 I5 v3 n2 g  ?: F3 S6 {% N
    , i3 C5 N2 L. K( L2 L' _
    至此,一个简单的爬虫请求就算是完成了。! a6 U8 T3 S6 q7 f5 {
    当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
    5 Y2 o; B, v" N0 a. tf、解析网址
    . J. a3 w; y8 f; _% n刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)' ~  m$ F' ^- L9 h+ A+ b
    BeautifulSoup:
    8 q. z8 L1 f8 |" I+ I首先导入需要的库文件:/ i( S0 \! Y; ~7 q2 l

    , A& F. m2 C9 f' ?" V5 z5 E0 }from bs4 import BeautifulSoup
    ( ?9 ~$ Z9 Q& f' |6 Z+ x/ {1
    3 `9 a2 O5 {3 X+ T' e/ _$ @; h4 j; P然后对上面请求得到的response进行解析:
    ! s. O$ e8 F6 r% x/ \
    ; n0 t$ J2 k2 K% d- r0 R+ dhtml = respone.content.decode('utf-8')8 i" V' e7 [# Q
    soup = BeautifulSoup(html, 'lxml')
    8 S0 I0 ^' i4 X* b0 C- v1% ^+ [8 K. c! d9 J
    29 _) v! H( D: V- ?& k3 Y; p: w
    以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
    ' w1 A$ j# e+ K( g2 f7 F- C# 获取head标签
    & {) W, ?4 k" m+ _6 t9 ?# Bprint('head标签内容', soup.head)' ^6 b, c/ c( }0 ]9 ?) h( I6 O
    # 获取title标签
    & n9 z, z% d: E5 b5 C- U  Lprint('head标签内容', soup.title)/ M4 c/ W: x5 u/ p
    # 获取body里面的img内容
    3 I" j; |4 X3 c' B9 P7 v) l8 n# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
    4 c5 Y" @- D, Z% @print(soup.body.a.img)   / r. E/ L7 {$ V: D! n
    # 获取所有的img标签  使用find_all()搜索整个soup对象
    % c' ~6 ]0 c! h$ U. F1 gprint("获取所有的img标签", soup.find_all('img'))
    + j2 I% `% K) _; A( y4 |. ]" C# 获取标签中的属性src地址# E9 @- f# R% r; G( {, \2 ^* k
    print("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值
    5 J7 X% P& q+ y- P3 L
    & J9 \0 O! M3 m: \& I2 t
    2 T7 S; v3 \' g+ ~- N# 获取soup的name
    # a8 s/ X: E" V5 v7 \! dprint("获取soup的name:",soup.name)* I+ {$ l- C' v
    # 获取a标签名
    ' N+ s% n+ k2 C4 C0 U! Hprint("a标签名字:",soup.a.name)5 X+ P7 P0 ^' p& t8 {, n
    tag = soup.a8 c4 X! f2 I! m' t2 T  |# ]+ c, Z
    print(tag)0 a5 k5 h( g5 d. N  o0 U1 A& Z
    # 修改操作  a标签改为b标签
    ) B! s$ n8 G3 Z  E0 @# k3 qtag.name = 'b'   # 赋值后<a> </a>变为<b> </b>
    % q. q" Q  h% G7 p. @4 U# 输出修改后的内容
    ) W& d  O% V5 F( l+ L# S' Kprint("输出修改后的内容:",tag)5 w. I' T5 r' E
    # 获取全部的属性 attrs
    7 l9 h' C  X! W# w2 T& ?print("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)
    ) q7 i1 y( S; {+ S0 g' G4 z: W9 o  E6 A; v' e& [# i
    # 获取属性的class的值   根据键取值
    * G4 O: D6 D: {! G+ t1 tprint("获取属性的class的值:",tag["class"])3 @% R# f! F. a* Z8 F# I+ e

      R8 {& M0 ]* z' Y$ [4 c! ^! j" }3 I5 U: j% f

    3 W: s1 n8 G- Z2 J* N* f; X+ s
    """针对获取的标签属性可以进行增删改查"""! Z* s( s+ b4 Y4 ^; F5 g
    # 修改
    4 ]( ?+ s# W. f: Z: D& Gtag["class"] = "Logo"
    ( v5 s: F/ \; g/ p0 o, s$ e8 ~print("tag对象的全部属性:",tag.attrs)
    0 G; t4 S, h. {4 O# \- E# 输出属性
    ) c0 s8 G" z2 g4 _; ^print("获取属性的class的值:",tag["class"])
    8 R( G1 m9 r# x- R# 新增  属性id  赋值logo$ o; L: K, ?$ w; E; Q( ~* W+ B
    tag['id'] = 'logo'. s4 U# k0 X) L+ o$ o: |' S3 Q
    print("tag对象的全部属性:",tag.attrs)
    7 `! V$ ?% p# v9 G- l; T$ E) C* v# 删除属性* \4 L9 t+ S7 J8 t. M" S: o  n
    del tag['class']
    5 }. P' [- b) }' L0 ?& n9 L) W8 e0 ~print("tag对象的全部属性:",tag.attrs)) c0 E# k3 ?) ~6 L/ Z

    & C# }. |$ X( B" W8 j8 y( U& d- o" ~  \: }
    2 K1 w: |5 P2 F# M4 H5 T2 }
    """针对内容操作  (只针对标签,对属性无效)""", i# m7 r* h5 e4 j/ T
    # 获取title标签内容
    2 A. g& ], G1 Z+ rtag = soup.title0 |; N5 c9 B. h5 E
    # 获取title字符串
    # R) b" Q, O2 K) Bprint("tag对象所包含的字符串:", tag.string)
    + R3 `8 ?' a: U- ]( X7 Dprint("类型:", type(tag.string))2 Q" |" P) U6 c" V1 }) Y) t
    # 替换内容
    # ^' L* @! T8 K. C' `' o( V& Ftag.string.replace_with("你好")
    / q  @* M7 w, ]9 `# aprint(tag.string)' M- o8 ^0 b' e
    # <!-- 学科建设 -->
    ! g& J+ M0 B, Y5 \6 R; V; F/ w# 获取注释文本内容
    # |1 S* j4 r7 G, pmarkup = '<b><!-- 学科建设 --></c>'
    ; F% l4 y4 t) o; H- ?; y0 r, @soup_comment = BeautifulSoup(markup, 'lxml')* ~' m8 s2 L. v0 {" r8 v$ E# \
    comment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索1 {6 ?) z) i* ^' D
    print("获取注释文本内容:", comment)$ Y' I6 s; }8 N9 h$ a% ^( ^6 }
    # get_text()
    6 J# D7 P5 U( @$ F% n" C$ Lprint("title的全部节点:",soup.find_all("title"))
    . B+ t8 n5 y' X! X4 r' zprint("title的内容:",soup.title.get_text())
    5 C6 @( c& G$ y/ l  w' B1 h"""查找ul元素标签""") J; a  X: t, i2 w
    # class是关键名,匹配时后面必须加下划线_; S) r- y5 v: f+ L
    # tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配  N, k, ]9 ~8 E5 [7 }' b7 [
    # print(tag)
    $ e6 @2 ^% h1 j) ]1 _tag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配: |" s* D* C, K9 m. S* z
    print(tag)1 ~- k1 d* u% g! Z- N* X+ f% H" P
    # 查找名称为a元素的标签内容
    ' i8 e' X: P- ?& s5 btaga = soup.find_all('a')/ h1 m2 h# }' g) \0 f1 g0 |+ c
    for tag in taga:3 \; j0 z( u% E7 E! i1 _3 |6 @
        print("查找名称为a元素的标签内容:", tag.string)+ E- J3 l' D3 v, a
    # get 获取属性信息  获取整个页面的img标签图片和src属性值
    ' E+ M0 D- _2 R, l" W, ltagings = soup.find_all('img')3 @( _/ s$ D& N; @/ v: N; W
    print(tagings)# ^& u9 }+ u4 X: ?2 U0 [
    # 循环输出图片地址1 s$ _; g$ ^) ^! y
    for imgsrc in tagings:
    * ?3 h6 n) M; D; q, p    print(url+imgsrc.get('src'))
    4 v' x6 k* t& v( m2 N9 V; f  m, |1 h5 k' w6 D% j
    """"属性只能做为参数,所有的操作只能针对标签"""
    : v& S7 c6 i8 A! @( b4 E6 w& O/ i9 [& p' e6 q* X5 K
    etree方法:7 W: o1 b; h5 O2 C1 A
    导入库文件:
    # M. e6 v7 b7 a2 l) s
    / F0 W$ i! l& U* W0 C  e, Ofrom lxml import etree( u8 a/ j8 ]; J" K  R
    1
    6 l+ L" A0 m  P' t* S5 b* J1 N! y解析得到的response对象;* U! Q2 @: n8 o5 Q+ K$ J5 ]
    2 @, q$ O. ]: @7 x1 B$ R
    # 设置response的字符集
    * J. @4 K# q% Uhtml = req.content.decode('utf-8')
    , n9 e4 ^6 R# R2 {4 ]# e# 解析对象
    " L) i4 G! D& p# _html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
    1 x$ x8 V4 q6 P! h/ I- V& r
    8 c3 s4 [6 K: U常用的方法:
    8 I  L1 v7 H5 p; R, u" P3 `3 u% v" A( e
    ' f$ u( l9 y% F
    # 定位head节点(元素), Z4 z; j0 x+ q% Q$ l6 n
    result1 = html.xpath('head')6 X: }: N: v7 Q: H( a3 i
    print(result1)
    5 u8 [7 H/ `0 ?( s" p; a; ^# 定位title节点5 d( X* ?+ h( K/ O' }2 v1 z8 T! u
    result2 = html.xpath('/html/head/title')( q* h! ?, v; D& [
    print(result2)
    9 U2 ^* ?. P( J8 R$ W8 {# 搜索节点  title节点4 h! i( {1 E8 Q" U
    result3 = html.xpath('//title')) ?" {. t1 _. l1 Z) C- L4 O: k& d
    print(result3)
    , |# T+ ^/ n" g( B+ m) ~# 搜索title内容  text()得到文本信息$ C. @9 g+ S$ W3 s, r- X! W. z
    result4 = html.xpath("//title/text()")- G  O  F: R) e- W6 q8 l: I
    print(result4)
    - J  f3 b+ b# s* T  u5 Z6 C! I# 搜索div节点
    : g' \) K1 a3 t  v  f* z4 b" {+ Mresult5 = html.xpath('//div')) q5 S8 Q+ ^  |4 m: d0 Z4 r
    print(result5)4 v) E5 ^" t- T% a  R, |* i
    # 搜索div节点 并用class属性定位% W) w5 i8 a8 e
    result6 = html.xpath('//div[@class="news"]')( O6 |  m  b2 J+ x# E1 r  _
    print(result6)
    - s0 ^" O- d# M) r; c# 搜索div节点 id属性定位* A/ {* O8 _* ?) S8 A
    result7 = html.xpath('//div[@id="news"]'). ~# t: Q: |& W  m3 q
    print(result7)
    3 R8 s, M0 F' y  q( y" n# 获取列表span信息& n* h3 w; m4 ^. M3 ~+ e' P
    text = html.xpath('//div[@class="news"]/a/span/text()')
    - D$ p9 T% ~$ n# i  j8 tprint(text)
    , |+ }! A. a3 K: Q$ s5 {! k
    & r! H4 c- E% t9 [  f0 S6 F

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存" r- A1 s/ G. N
    保存的方式有很多种:) b& |& @" k  R$ P7 F/ u! @$ k
    1、保存至文件
    ! ]2 P% J  }2 |8 Y. vcsv、json、text
    4 Q- A( _; I3 W$ t: K' y9 q" C) r2、保存至数据库# @, y; R4 w' N, W/ U% B* R% z3 S
    MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍5 q% H* `# L2 f
    / _: p; o9 c+ ?  r
    # P4 ^# `) `) ^. V  S1 j
    ————————————————4 G0 e- i: Q# w" [5 p3 D, x& G9 ?
    版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    8 Q- k( r. J( }9 F( P( ]原文链接:https://blog.csdn.net/royallucky/article/details/105930473' D9 f3 L) X, v; P; o. F

    , `- F5 X2 j7 F0 ^5 {  n( f5 t8 Q- s& z
    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-4-11 19:28 , Processed in 0.341272 second(s), 56 queries .

    回顶部