QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3664|回复: 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
    ) G# F8 l2 E- c6 \  I

    ) w) W( V' L6 j
    " ^; D6 z7 ~3 x$ S# e) A
    手把手带你5分钟搞定爬虫(聚焦爬虫)

    8 y4 s% F) ?5 K  t/ ~% g
    $ t2 N0 O: l& B9 O, Q: |爬虫的原理
    ) v# a0 H/ d3 l8 R3 L" S4 w( z! f' c  W( H
    对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫. R% j  o& N5 |
    把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味
    $ z$ a2 R9 s0 ~# _: C% Z所以说爬虫分为三部曲:: p2 ?: n! L3 A$ A" Z8 J
    1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)
    - k: t+ W! b" N" s2、去找到你喜欢的食物的位置(得到目标地址)
    , B% C' c, i1 e$ @1 U3、把食物搬回家去(解析网址,获取数据,存储数据)& F. y* |4 b# Z2 v
    它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
    & C" V2 L- S5 wa、导入需要的库 requests% o! ]. g4 t6 d8 l
      k! P( n  M- ~3 u0 m6 F
    import requests
    2 D. h6 C6 I  \: r: Y1
    ! h( X( D* a/ x- ], rb、明确你要获取数据的网址(这里以百度网站为例)
    # N) `- M9 V8 F9 \" ^( z
    ! j; ?4 J! j& I+ v# p& t( ?url = 'http://www.baidu.com'
    & p& Z; v, F! q- M( N( K& ]1
    0 `" D: e3 `- m: O. c' q0 bc、创建请求& F) T$ g5 w6 o4 _( V# x" m! C

    * o( }! n! p5 b# r3 a" P8 v+ a$ Oresponse =  requests.get(url)! i3 Q) }9 \+ v) n4 N# u$ l1 v7 V
    12 D: U; x) Q  [& J5 ]$ m9 J' A, D( q
    d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
    ! H2 ^5 o  ]4 i! `6 T4 {1 G; W( g: f  o
    print("状态码:",response.status_code)
    3 N5 @( Z& c; o% c8 K1/ [- j2 U' |* N0 R2 m# ^8 R- c& m
    当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url8 ^. U$ A: T+ W- A
    e、得到网页源码! ?: }2 l( `5 w( r. R/ v' l+ r: Y; j

    1 A( m9 \7 h8 F$ t. J2 n; B5 e$ _print("内容:",response.text)
    / Q/ r; x  y  A! b; C# \11 K7 E4 j5 v' w: s' l. k
    response.content是response.text的二进制形式; u: c' O6 Y8 \6 q5 C) ^8 r
    5 Z8 N+ H/ J7 i
    至此,一个简单的爬虫请求就算是完成了。, E& l4 C- [, }% P
    当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据! f) t3 W  f- b# Z% _0 Q
    f、解析网址3 u5 ^1 u( V6 `. F# X
    刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
    6 ~, t5 |2 E4 j0 `! l5 H+ OBeautifulSoup:  c8 ]( P$ s! @0 Y, {& x( m/ h3 f+ Z; M
    首先导入需要的库文件:
    ( k  [) f1 |! r0 j* b2 p( {6 P! x6 A* N; `3 ~" e
    from bs4 import BeautifulSoup
      l" `4 H: Y2 }: o1
    & V. y+ |  s+ v2 W' r) M7 R然后对上面请求得到的response进行解析:
    % l. J+ ]( ^- Q- P( f
    3 {6 z' |, @1 L& N0 r1 A& bhtml = respone.content.decode('utf-8')/ P" G. E6 v) G# ~- G, n+ a  @
    soup = BeautifulSoup(html, 'lxml')% N! @& _1 J1 d' n; i
    1
    # ~' v! H# a! G* y% Q2
    . h; `& s& y% ?以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:8 x, X5 E0 K+ F3 B: ^2 R: ~$ F
    # 获取head标签( W  Q) O4 q- m# y. B$ T  h  m! d2 h
    print('head标签内容', soup.head): N) x1 s8 J) J  i1 Q& g
    # 获取title标签% c& s, g3 h0 W* |( I
    print('head标签内容', soup.title)
    ( S/ n7 u$ C  C$ j# 获取body里面的img内容
    2 O* N4 E0 d9 w- D; E3 L# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签), P8 l. V* J( r
    print(soup.body.a.img)   4 c. a6 F5 `+ A, Q
    # 获取所有的img标签  使用find_all()搜索整个soup对象4 q  H6 i+ Z* i0 Z# j' z
    print("获取所有的img标签", soup.find_all('img'))2 M  x% r, U- L
    # 获取标签中的属性src地址
    . H& o5 B! B! n7 M3 m  @* Y8 T3 Lprint("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值% `. ]; ?. W3 V' J; @! I

    5 `: l; n/ q* I5 I$ y  g8 ^3 F# ]+ M" ]9 k5 ]5 C8 h4 c
    # 获取soup的name* T$ A4 t% Z/ D0 h' @; @) J9 u% o8 b
    print("获取soup的name:",soup.name)
    , N7 v" |* @  R- h3 D- x# 获取a标签名% ~% E- N2 e8 G1 _: [1 {
    print("a标签名字:",soup.a.name)
    " v9 P9 v) E2 k9 m; _% ktag = soup.a
    8 @1 o/ L& u2 t' X, Y$ Nprint(tag)
    * u9 q# I$ J* H; g- ?3 Q) j9 v# 修改操作  a标签改为b标签+ ^' U* N6 d- b' k/ y+ l$ F
    tag.name = 'b'   # 赋值后<a> </a>变为<b> </b>2 N% h% ?/ x3 Q5 p- ^
    # 输出修改后的内容
    5 C: u9 W/ u, x2 Jprint("输出修改后的内容:",tag)
    ; v0 Y( c4 a& q3 b2 W# 获取全部的属性 attrs& B6 C. g; O% W/ Q+ |
    print("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)
    : C& Z- K9 [! U. o! d. v, A  M7 G4 K  k8 t4 h& t) M
    # 获取属性的class的值   根据键取值/ ]6 P8 Z( `  x# w5 X: }
    print("获取属性的class的值:",tag["class"])
    ) u% m0 I( u7 D& T2 T: Y8 a, g1 q. W& ?5 {" ]( M
    + [/ N( c8 d0 r; b" E

    * N1 N8 F" x' ?" g
    & e' m+ `5 s# E" V2 ], E"""针对获取的标签属性可以进行增删改查"""
    ) N% w0 b" k) S3 x# 修改4 A. b2 ?+ v3 B, D3 e8 ^) X2 R
    tag["class"] = "Logo"
    ! Q# O' Y) m5 Q2 {% {) vprint("tag对象的全部属性:",tag.attrs)1 t, w5 e! G! J; Y' ?
    # 输出属性8 r: [" _  [, s( D) I, u5 j
    print("获取属性的class的值:",tag["class"])% v6 M# I2 }$ t; b. V
    # 新增  属性id  赋值logo
    + r$ A6 W6 J, ftag['id'] = 'logo'" H- }" v$ h3 i% [
    print("tag对象的全部属性:",tag.attrs)
    # ]* ^' E% D2 g3 B% m0 w: [/ r3 Y# 删除属性
    . q/ t2 T* T8 ], d9 {% `- Jdel tag['class']! J$ A1 v8 x/ R% ~, x2 N) T5 Y
    print("tag对象的全部属性:",tag.attrs)' F, r& B9 A: |

    + @) Q" j2 P) _# Z1 l9 Q0 z9 e( W3 j" x6 Z
    6 A" ^. \6 M# o7 W
    """针对内容操作  (只针对标签,对属性无效)"""
    9 `: `/ {+ Y; I4 u- h1 ~# 获取title标签内容
    ) [1 o( c8 F' }/ x! Ntag = soup.title
    : ~' V* ?- V* ]# 获取title字符串' M4 H0 L0 w; ~/ o; ?0 w: ~: J
    print("tag对象所包含的字符串:", tag.string); `9 ~) K6 ~( G+ e! X" @
    print("类型:", type(tag.string)). {- ~7 ?0 v9 ~' h5 d5 Y
    # 替换内容
    " k+ s6 u2 q$ V% r3 {, b; Etag.string.replace_with("你好")9 `5 p; h3 I# k7 s9 d
    print(tag.string)
    6 c* e% z4 U  ~! e# <!-- 学科建设 -->3 U: B5 h$ I6 b. S4 w1 {
    # 获取注释文本内容4 l2 |: ^8 V0 i, h' r
    markup = '<b><!-- 学科建设 --></c>'1 D  ^. N7 n; ^4 ^% n( p
    soup_comment = BeautifulSoup(markup, 'lxml')1 W- h( H2 G4 H$ C7 K4 R' C
    comment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索
    5 R0 f8 U+ F8 |1 tprint("获取注释文本内容:", comment)$ S. }% r# R% F
    # get_text(). x+ B. [; d3 F9 P3 @6 d2 |! T
    print("title的全部节点:",soup.find_all("title"))
    , d, U$ E9 x' M# f& b- G- Mprint("title的内容:",soup.title.get_text())
    5 d& x3 X/ A& S6 C( f+ `" c5 G"""查找ul元素标签"""9 l+ S( o% S8 R
    # class是关键名,匹配时后面必须加下划线_
    7 H( U1 h; W+ Q" ?, c# tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配7 D- g: t% J7 ~# u" U
    # print(tag)3 l$ C% }' ~9 j4 l$ h
    tag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配5 l% \/ m; R) U4 a
    print(tag)1 F5 B' j: t( d/ h  Y
    # 查找名称为a元素的标签内容
    9 h7 a7 G" p& z$ r$ O4 v7 G3 Ntaga = soup.find_all('a')* |2 U" h# p3 J, f9 O" S. Z
    for tag in taga:5 D9 h6 {4 [5 ^" k# Q; Y
        print("查找名称为a元素的标签内容:", tag.string)
    $ l& z% l8 l7 S9 J% @# get 获取属性信息  获取整个页面的img标签图片和src属性值2 i) C$ \7 T+ h7 b4 H8 r5 t
    tagings = soup.find_all('img')
      K' M! `# a3 ^* I/ l+ xprint(tagings)* j9 I" }9 L) l; g
    # 循环输出图片地址9 N* d6 h' Z0 f9 Y7 Q1 \
    for imgsrc in tagings:
    9 T. \* B6 Y' F: g7 x* {; m- @' i- O    print(url+imgsrc.get('src'))7 e  h6 n+ j* P+ l
    ; z( k$ P$ X  [/ k
    """"属性只能做为参数,所有的操作只能针对标签"""( n+ G2 q) u# r: ~/ Y. x
    7 q5 U0 H, a' D: P1 `/ q0 Q
    etree方法:
    2 g: ~& @. x3 H. ^' M6 h8 [导入库文件:
    / c0 v  G9 e$ y5 s! p+ Z
    " W& a- Q( [1 F0 F6 k" A4 ifrom lxml import etree7 I/ X4 s- z. x$ f6 j6 W
    1, p" a0 B3 N5 _1 i
    解析得到的response对象;
    , n9 `/ k( x( O; ~8 v+ h
    . {; p2 R5 X5 R" G+ x/ {( V# 设置response的字符集# d. r, }$ F: M& r- a
    html = req.content.decode('utf-8')
    2 h* {& D0 Z6 b, ~9 A8 y# 解析对象
    ! M- a6 q, z( @, mhtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
      _4 u  p5 G+ G) v3 M  A: K, r' l. g- A+ h6 P2 H3 D, t
    常用的方法:" ^' Y; o7 X5 f7 D6 }1 C
    " E( e2 C; P& x9 x' {" r8 }& K4 _
    , m0 G1 s4 Y# P4 Q
    # 定位head节点(元素)3 e: y4 [% h& j+ v' J
    result1 = html.xpath('head')
    - D0 E+ d/ c8 p, N3 q' R5 ~8 hprint(result1)& d. A* X8 i, v4 [9 s
    # 定位title节点
    * f+ [# v9 y& presult2 = html.xpath('/html/head/title')
    4 s! O9 J$ X7 G; pprint(result2)) z: ~9 f' X% A& O# }9 d8 \* \
    # 搜索节点  title节点: d2 P" i2 X8 ]2 E* y  N
    result3 = html.xpath('//title')8 E# t8 e2 T9 B; r9 T6 a8 Q
    print(result3)3 C. @; t# \. V$ _% i8 N+ w, R% _8 I8 B- U
    # 搜索title内容  text()得到文本信息
      S, `$ P# h8 Q0 n0 ?. y& n. Rresult4 = html.xpath("//title/text()")
    " g2 r, Z: d: E. t3 j0 y! Y7 Gprint(result4)
    ! M$ ?7 H. _6 N# 搜索div节点
    ; ^( b* d# Z1 _; ?9 F& j2 m4 \result5 = html.xpath('//div')
    ) F1 R% _7 l2 v2 @* nprint(result5)  [, b1 P. R* }( \* X
    # 搜索div节点 并用class属性定位
      L( ]3 [0 v7 w+ R1 Nresult6 = html.xpath('//div[@class="news"]')
      B( z9 u- L' Rprint(result6)
    2 x2 L$ h$ r1 a" s& G; x# 搜索div节点 id属性定位
    , R- y$ ?3 A' O( |4 R! h% q7 h1 h5 Qresult7 = html.xpath('//div[@id="news"]')! I1 [2 p9 H8 j$ u: o2 R
    print(result7)
    8 `' \$ y7 f* E6 b8 j7 I0 D1 r# 获取列表span信息
    * h) |+ O' c0 n6 A+ N* ^9 [3 dtext = html.xpath('//div[@class="news"]/a/span/text()')# Y+ ?2 ]& s: e
    print(text)
    ) W; ^* @! Y9 b2 [& M7 ~$ _6 b! [" e* C6 D

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
    + Q& I2 C" _1 Z: q保存的方式有很多种:- q, E. X4 e8 Q; \: }9 V$ N
    1、保存至文件7 t' q, L9 V$ J
    csv、json、text
    4 Z) p* `1 Y3 l9 {+ E( W; Y+ M3 C2、保存至数据库9 K# y" ?8 v+ A1 w
    MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍
    ! O9 H* p1 d) K* O+ \. R3 u$ d0 s/ T7 q% N- f
    + n1 {+ S2 J7 N" n* A  B
    ————————————————7 e: t3 v, w# O* P2 V
    版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。0 L' u& q+ a0 }- B  S
    原文链接:https://blog.csdn.net/royallucky/article/details/105930473. @" h2 L% M- w! m! C
    8 n3 Y' T: _5 p: K

    , v6 B4 L' i  {8 o7 v
    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-15 14:13 , Processed in 0.418010 second(s), 55 queries .

    回顶部