QQ登录

只需要一步,快速开始

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

    ) m9 k# h+ z7 b
    - t% C  B' W7 I  n1 A5 W

    : R( U( e- ]  u) V
    手把手带你5分钟搞定爬虫(聚焦爬虫)
    & ]$ I, `9 _2 X/ P+ n( `
    - r% ~+ q+ M6 R9 O* z3 |3 q
    爬虫的原理* z) K5 s; ?. O. t
    " e! j$ W# E/ h1 O: B5 S# p
    对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫( \! P2 f! l! ^8 H9 ^% @& c
    把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味6 N( R3 u+ K4 K, R% q0 p$ K
    所以说爬虫分为三部曲:
    9 ?* a* H4 g  P1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)
    + ~  T. L; m7 p2 s) H- \3 z2、去找到你喜欢的食物的位置(得到目标地址)# b0 P' B0 ]4 v* h% s
    3、把食物搬回家去(解析网址,获取数据,存储数据)
    " p- {2 }/ O- a$ C它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)% b$ e; L) d! f
    a、导入需要的库 requests
    ) n1 g) a  b9 \# T6 u1 Z0 F" I+ Q% D# |7 G, m2 S
    import requests/ Y) V8 H% D) X0 P# V  ^- f* }0 z
    1
    7 _$ L9 o! p+ Z$ Q6 C& Fb、明确你要获取数据的网址(这里以百度网站为例)
    " H0 l0 D( g7 Z0 ]% I+ e0 `8 v1 [$ [' Y' R
    url = 'http://www.baidu.com'
    ! e: p% a$ C# L4 k% [18 k+ K7 s8 z  a+ Z% p; z
    c、创建请求4 w4 u. b# m3 ~5 h. ~  k2 ?
    + Q6 O$ m# _4 ^' L7 ?
    response =  requests.get(url)
    3 }) m- G0 Q, h/ U1
    3 b# Y, q) [& j$ ^7 u8 B& Zd、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的): }9 |5 a& L3 l; k. Q5 \+ \6 L

      R; J/ t! s4 |$ M, I  ]print("状态码:",response.status_code)* x4 @" `$ F" {- X
    1
    ' P- R5 l+ x' P当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url. ]/ v. E/ i& t0 c2 d5 y! O0 I
    e、得到网页源码
    4 {5 g0 D9 c" c( S( V" l
    - Q# K' b5 N: R/ C! a; o5 |  d( I1 zprint("内容:",response.text). g, G4 c; B1 \/ j. U1 O! y% `
    1! m, z7 W) J0 y( D  q1 g. q
    response.content是response.text的二进制形式- D7 ^7 F* }( m

    & ], o6 D  D5 L: q* X. F8 m至此,一个简单的爬虫请求就算是完成了。# |, Q8 n/ b" z( P) t1 B4 O1 p
    当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据/ M  |" f: S+ u
    f、解析网址% R& R/ x) h% x5 N" U+ ^5 O
    刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
    0 T/ n3 t4 f# D# GBeautifulSoup:
    6 F4 r  P3 _3 |( r# ]首先导入需要的库文件:
    0 K3 S  x: F2 ^; Y9 r" {2 k( o+ W- a. ~3 m! ~! x
    from bs4 import BeautifulSoup
    6 n% N* ]6 Z0 G1 B# N# K1
    * c! A" Q' z  s- J9 G然后对上面请求得到的response进行解析:
    7 h4 v7 I/ D8 X3 ~. C6 r! i* P1 E; J+ L( v
    html = respone.content.decode('utf-8')
    ' A) l$ B" s7 g5 R5 g- Vsoup = BeautifulSoup(html, 'lxml')/ j& [  H* F+ }% O  M+ g3 _
    1
    ! d" i0 ?. p% I: k+ f2& y  N8 y6 N! G& F1 s: j+ `. o
    以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
    + Y7 k& T+ F8 q/ U0 G% s# 获取head标签
    6 y9 Z: V( r* m2 Zprint('head标签内容', soup.head)
    1 b# D& ~. E/ T$ x: D6 I5 _# 获取title标签0 j) {/ N: ~+ D3 y; C' S. H
    print('head标签内容', soup.title)* h1 Z2 C' @: W' q  F5 z- K2 ^- \
    # 获取body里面的img内容, n$ J* r) u$ h0 `6 K/ k% O) J
    # 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
    2 o- x0 q7 R* j7 q) {7 |% B: {print(soup.body.a.img)   * ?7 Y$ ]9 {" X3 g) l1 z
    # 获取所有的img标签  使用find_all()搜索整个soup对象
    : J/ o5 Z) Z6 X; z$ N" i" b9 L1 `print("获取所有的img标签", soup.find_all('img'))
    ; D0 D5 K; k9 _/ r- D! ~# 获取标签中的属性src地址
    " s6 F7 h$ d+ O7 r$ C5 N3 Qprint("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值2 Z7 E! K7 ^! W8 C% H* H. P

    ; n  y. W! Q, c  G6 E* y( J; a" m/ q6 t) Q4 J- o% h
    # 获取soup的name) _3 f+ X( \  A, Z  C5 p2 z
    print("获取soup的name:",soup.name)
    * L- ]: O2 m: _4 u+ s# V* w# 获取a标签名
    & d/ X" p# v* u6 S5 o/ ~0 c5 nprint("a标签名字:",soup.a.name)4 a* m8 L! m2 }% I* A
    tag = soup.a
    7 ?0 J- f8 L( l3 yprint(tag), K( R* {! A: Y2 E5 }  H0 k* m
    # 修改操作  a标签改为b标签' g: m3 h/ g0 {- T
    tag.name = 'b'   # 赋值后<a> </a>变为<b> </b>; G/ L6 i" y: U! _( ^6 \
    # 输出修改后的内容1 S1 d2 W7 g' y8 l! w& R# z
    print("输出修改后的内容:",tag)
    & K+ F7 L3 W' s7 |( T3 t# 获取全部的属性 attrs
    % P! N9 ]: z& eprint("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)5 |  ?0 x9 {: u* \- C( n% O
    . z; L8 q$ E8 }3 |" M3 X% w9 t
    # 获取属性的class的值   根据键取值
    5 `* D4 x0 d' h2 Q: l4 S4 V1 Nprint("获取属性的class的值:",tag["class"])
    * ^- ^- p" M6 T8 ~4 k0 O# [0 T7 |. k

    # z8 B, ]! X1 ]8 x
    & c- S6 L: n6 x( K$ }4 b0 L& Y; T3 l9 P: u' i. X1 p1 s- f4 S; s" W
    """针对获取的标签属性可以进行增删改查"""
    . i' }( t0 z+ n2 R0 F% `# 修改
    5 Y! }" R; |# C( U' M5 qtag["class"] = "Logo"8 w& ^* u. x7 B/ ]; x7 o9 `4 J1 q
    print("tag对象的全部属性:",tag.attrs)
    8 j8 q( H3 u; t/ _, R6 K# 输出属性
    9 P7 N/ l& P% M( L; eprint("获取属性的class的值:",tag["class"])2 X/ H7 S) u; A) F
    # 新增  属性id  赋值logo- E$ `; c. J3 @- Y9 }! s
    tag['id'] = 'logo'5 k% i  j( Y* X/ U; u; s
    print("tag对象的全部属性:",tag.attrs)& [3 s9 G: U+ L9 L
    # 删除属性
    ; E1 }" V2 x" s1 ^8 `# rdel tag['class']
    # P, [( V: C( u1 W' b" hprint("tag对象的全部属性:",tag.attrs)  @. v' n5 {  ?1 M
    . v! |8 i6 r' ]1 z; N1 Q; l

    + }5 H# C: O( n4 R& I3 S+ l- D
    . ~3 r& D  g; e2 F# m( e" h! E; M"""针对内容操作  (只针对标签,对属性无效)""": \7 [* u4 y+ l+ z  T& }
    # 获取title标签内容
    - A3 V  |3 s/ t$ z, Qtag = soup.title
    1 K8 {, h5 Q. u# 获取title字符串
    " W, A* C3 r% y1 N! wprint("tag对象所包含的字符串:", tag.string)/ e- s8 F6 D, `$ x( m
    print("类型:", type(tag.string))
    & A/ x6 ^% A% t: P: ^. {# 替换内容
    ; s1 n: k& j# u+ `: Itag.string.replace_with("你好")* v1 ~9 V0 b. w" S1 k) O) }# Y
    print(tag.string)
    : ~0 U7 b2 A) s! P) V0 l9 e# <!-- 学科建设 -->
    8 b5 f* {% T- T6 w; B' O8 G, ?8 M# 获取注释文本内容
    ' l- o# j, K0 ]; c8 t5 Gmarkup = '<b><!-- 学科建设 --></c>') w: ~" `3 P  l( H0 x
    soup_comment = BeautifulSoup(markup, 'lxml')& |  }6 u  w4 ]7 F3 c1 H8 w
    comment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索; ^; ^& t4 E' A* M8 R. w
    print("获取注释文本内容:", comment)1 a( y% Z; A) K5 _# Z( v
    # get_text()& w4 U/ F: a; L. e5 A2 _" R/ Y$ {
    print("title的全部节点:",soup.find_all("title"))
    6 r+ f6 ^, d4 j5 M) |: Xprint("title的内容:",soup.title.get_text())
    ( c( @# v) ^. h  M; L"""查找ul元素标签"""
    7 m/ |% i1 r0 j" y# f3 i2 F# class是关键名,匹配时后面必须加下划线_8 o; @$ w* x8 M6 c; @  |1 {+ R9 C  ~
    # tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配9 E" o5 P9 C9 f
    # print(tag)
    + w( q. }% P# Y: N1 D. C1 @tag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配
    ( a, a) ]% `, Z% Zprint(tag)8 w7 ]2 x, o3 b& W& n/ w
    # 查找名称为a元素的标签内容
    ; c: Y2 T  M( `+ \; A  [' E! Xtaga = soup.find_all('a')
    ; S0 }; ~# j7 [) j& ffor tag in taga:
    ( ^" d- p& g! z" `, a7 p    print("查找名称为a元素的标签内容:", tag.string)9 a- B0 l/ t+ V' O: y' Z" U
    # get 获取属性信息  获取整个页面的img标签图片和src属性值
    ) G* K, O# F. [# Htagings = soup.find_all('img')! j0 i8 A0 [2 M3 Q. a% `/ A9 {
    print(tagings)
    8 i1 q3 Q, ^6 G/ Y- Q# 循环输出图片地址
    9 p8 d0 h- f! G6 Afor imgsrc in tagings:
    0 S$ a5 Y: A/ L$ B3 f- W    print(url+imgsrc.get('src'))9 ?2 C% d5 u/ u) I$ v
    : q9 @0 s* ?. u+ k
    """"属性只能做为参数,所有的操作只能针对标签"""  L+ @) G8 ^) F) g0 |* p

    1 j4 C( |% I7 M/ I3 C6 {$ C$ Getree方法:5 }7 {, m, B  K
    导入库文件:
    , c* ?3 k, F( U& U2 m3 V( P) ]. B4 B$ x  U  J6 D9 r) h
    from lxml import etree6 m& _: \% w% C/ v5 v6 f" i3 S
    1
    * t0 I* z) W1 N- L解析得到的response对象;
    2 L% K; s( X" s/ K' f: H
    , g& y! e5 D& a% s3 y# 设置response的字符集
    , p8 _* `" R( R& Shtml = req.content.decode('utf-8')
    ' Q; E! j. l  a- N# 解析对象8 @1 f1 ^" l; z0 a% p3 Q- k% `% X
    html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
    8 a  [# r" J/ b; H! `" D( p
      T: P3 h0 ~; A* K  j常用的方法:
    5 \7 c, j3 L( n  k: J8 ]5 y* ?7 h) D# p

    $ Q7 D  \! U3 f1 O# 定位head节点(元素)
    - \0 l, A( w5 R+ M: ?: P3 mresult1 = html.xpath('head')7 r  n% `; x8 C, V
    print(result1)2 {$ z( X. A1 Z# J
    # 定位title节点3 J8 G7 N" A" Z% M
    result2 = html.xpath('/html/head/title')4 y: d8 Y* D' v; a- ^) ]
    print(result2)
    # F6 L2 J0 m- G' J  y; z# 搜索节点  title节点
    7 N* P/ i- \' T3 w8 Fresult3 = html.xpath('//title')& b8 k$ i5 d/ g; N- h7 K, f
    print(result3)
    " @% s2 l9 i/ W6 \7 Y$ ]" L# 搜索title内容  text()得到文本信息! Q- K9 h: y/ I! i0 e4 }; {  x) S
    result4 = html.xpath("//title/text()")
    + l; O$ u- t; e+ E4 s) b+ K$ xprint(result4)# O8 Q* A& M9 G. R' W& D7 x: T
    # 搜索div节点0 M$ Y" y' \! |3 A# }7 W
    result5 = html.xpath('//div')8 U2 j* X2 `3 H$ j6 `6 n' G
    print(result5)
    3 i) O$ k. n0 u2 C8 Q. ~4 n* i2 f# 搜索div节点 并用class属性定位' |+ ]+ D6 v- e5 V  S( v
    result6 = html.xpath('//div[@class="news"]')
    $ \7 f# C( Y; r' _* Z# w- G6 Jprint(result6)
    $ ^% @6 |1 C4 e7 z1 Y1 G# 搜索div节点 id属性定位
    & J7 K: e* B# J5 K7 Q2 jresult7 = html.xpath('//div[@id="news"]')
    ( D3 P2 Z( V; p( G" Y. fprint(result7)
    ; t1 z, G' }& @1 e; P# 获取列表span信息
    7 H  z1 ?, @) r0 W) ftext = html.xpath('//div[@class="news"]/a/span/text()'). t* O* j: q/ U9 p3 u/ O1 u
    print(text)
    ! {& Y# q! D3 s* i1 F. k) O5 c5 T2 _/ Y- ?  F' M

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存9 {! k2 n, M) Q1 C! M
    保存的方式有很多种:0 r3 T$ h9 {2 u) F; L  p8 {* Y
    1、保存至文件
    2 l) A' U" {/ v, Mcsv、json、text
    ) p( e+ A7 B0 L" W/ T' m$ ]  V9 S$ Y. `2、保存至数据库
    # ~4 t0 x- @% N% l" h5 RMySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍2 K( o/ Z) n/ b; K; F7 F/ e

    8 X* t; [. A+ p9 |' b8 G
    : a, X+ E6 B+ U7 e, _————————————————, j5 m/ ]$ `) O) n, Y
    版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
      W% S5 R9 E5 P: L5 E5 f原文链接:https://blog.csdn.net/royallucky/article/details/105930473
    5 v  N$ K* X. `" @' Q  \) C2 j
    0 U; y+ j' s' I4 A
    # q  u1 d/ o. T# S5 G1 `3 X
    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-5-27 09:47 , Processed in 0.456401 second(s), 56 queries .

    回顶部