QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3744|回复: 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
    ! a& X- c; Q, [1 l" B3 E, s4 ~8 q+ |
    ; y5 U. \* a  k6 l- G+ p1 c
    , W2 R- O8 ^6 d1 W+ R! ]- {. N5 X
    手把手带你5分钟搞定爬虫(聚焦爬虫)
    0 x- L0 w2 ~3 E$ c9 F- ~, n
    0 s, J$ ^/ J, \
    爬虫的原理
    8 r  _& t7 a/ n$ s& _3 H: R  ?
    % R+ _3 u: a2 v0 N8 r% |对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
    ' N. {- `& A3 a2 H% u把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味
    9 O7 @7 A$ G5 V所以说爬虫分为三部曲:
    3 f. g* C' b  Y, ^9 I, }9 T, o& L1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)2 ~& n1 {! B5 I
    2、去找到你喜欢的食物的位置(得到目标地址)8 C* C3 a8 u) d5 m) u& p; \
    3、把食物搬回家去(解析网址,获取数据,存储数据)
    ! k$ ~/ q  G7 t! d, a& {' P它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)7 ~$ n' E: q* w4 o( p
    a、导入需要的库 requests
    ( p3 {- |( M) r! w
    $ d3 `( T  Z5 U8 X0 ^3 |import requests1 e4 E2 `. F5 d7 o2 u
    1# t$ u9 M& n/ r2 Z% ~( H* _; m# A
    b、明确你要获取数据的网址(这里以百度网站为例)
    , N/ o9 k! `0 a- J, O/ P+ ^* f
    url = 'http://www.baidu.com'
    , Y- x- \) F; r% o6 k1
    - S8 l* o+ q8 q+ ?. Nc、创建请求% J& y* y* G2 k$ X% C  ?4 P6 S# r

    0 R0 q3 M' p' e' `  W- \response =  requests.get(url)( n5 I6 E! O/ d! l( |
    14 @9 l" a, Y  A
    d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
    " D: P) S  {; Q1 {3 k# G* c
    4 i# ^; D+ d: r8 Qprint("状态码:",response.status_code)1 d6 M; n: O2 R- d" M  N7 ^( o
    1- {; C  P( j7 r
    当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
    & I: r& L5 l1 f2 T8 Se、得到网页源码7 M! }2 i8 y. k/ {7 P3 ?
    % X1 {  U7 w1 W" f3 J+ N" q
    print("内容:",response.text)/ ~8 P; _# `4 h1 z- k6 \' V6 g" Q
    1# H% R5 l+ |2 V. Q' S
    response.content是response.text的二进制形式
    * Y, e+ C5 V/ A' L. g0 k6 N, c
    9 E( y% m1 P% x1 F# L3 Y- Y至此,一个简单的爬虫请求就算是完成了。
    4 B7 d1 o* F9 e1 O当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
    2 y4 T8 @' t4 X2 I+ \- `f、解析网址
    5 m! F! \2 [! b! |- v- d刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)0 V4 ~# U* d/ Q% ^% v! z- [6 a
    BeautifulSoup:
    ! c) i9 ]1 f8 I/ h首先导入需要的库文件:- ~) |, T0 g% C- Q

    5 \: V" g8 ?+ M+ l9 Rfrom bs4 import BeautifulSoup
    / T# c) M; `& |1& {9 r& P/ {8 o& m( `. l
    然后对上面请求得到的response进行解析:: A8 j8 |$ D- x) E" E% H

    ( o- C+ b+ @: C9 \( M0 t  Lhtml = respone.content.decode('utf-8')
    , F/ X0 B- R" i& C* {, n' ]3 E: ?soup = BeautifulSoup(html, 'lxml')
    + v. s" D9 A2 [: u- q# @1
    , ^1 i. e7 \/ K" |/ L+ E25 ]3 U( N2 p( f% J4 I* U$ _& i
    以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:) I1 c6 p3 d8 s$ p  J& i% S
    # 获取head标签
    / H3 z, k" ?5 X( e& ]8 y$ v+ [/ kprint('head标签内容', soup.head)) m& E4 k7 J+ h: k0 n# H" a
    # 获取title标签, d1 |2 L" P+ ~/ ], [
    print('head标签内容', soup.title)+ u% n  R4 W6 J
    # 获取body里面的img内容( l; }5 |, \5 {6 ]" M0 Z/ X
    # 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
    0 F. T# b0 Q( t6 ?  o# x6 B% Uprint(soup.body.a.img)   
    * e7 N# ^  ]$ _% m( q: \# 获取所有的img标签  使用find_all()搜索整个soup对象
    ; l% P* Y9 k/ V8 Bprint("获取所有的img标签", soup.find_all('img'))5 T( z( i* c& J- X+ V# r$ O! W* N+ ?
    # 获取标签中的属性src地址; Z8 v: ?9 }7 F& m
    print("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值
    3 G+ s, d( b1 N( n" i: w
    7 X! b  b7 D3 @, ~
    ( s- H' l( k  r8 z8 [5 }9 i8 @# 获取soup的name
    ! G5 x) g6 l4 L( ^6 d0 Rprint("获取soup的name:",soup.name)
    8 _2 }2 T" t- R" \9 P# 获取a标签名
    ; B8 v: }+ L: u7 r6 @  \) j0 Sprint("a标签名字:",soup.a.name)
    ) a: r& y. m* M6 etag = soup.a
    ) W( Q6 Z5 E( o  E: N% e- @print(tag)
    , f: d" U+ f3 U3 j# 修改操作  a标签改为b标签
    $ o1 Z) i6 }/ Y7 c; s+ r8 ztag.name = 'b'   # 赋值后<a> </a>变为<b> </b>
    & \- Z9 U  T& u* v: |+ \, ?0 J$ G# 输出修改后的内容
    : _7 z% O% ]; k' Sprint("输出修改后的内容:",tag)
    . m7 @5 N& r2 R9 n. C# 获取全部的属性 attrs( r% V$ v- s, \: d
    print("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)
    ' i6 t" B& ]( S  d, H7 g
    . N, y6 J5 U& ]7 Q# 获取属性的class的值   根据键取值
    # s( c: A9 t3 f- j# Gprint("获取属性的class的值:",tag["class"])
    9 x4 x# @  j, n/ h5 j/ I# }) M& T
    0 G7 s' y7 X  ?3 S
    $ I9 y7 ?* i+ I4 ?8 n4 q9 m7 n) E: H0 p2 q/ K* B% ]6 M: s) c
    / i# e$ s5 u3 E9 \( A
    """针对获取的标签属性可以进行增删改查"""
    1 j3 I& q5 ^5 N' o# 修改" L+ K5 w7 E* F" ]
    tag["class"] = "Logo"
    & D. u: ~. D/ y" bprint("tag对象的全部属性:",tag.attrs)1 _8 O. T2 v2 [: u
    # 输出属性4 q# w! @# a' j0 K& @3 q0 _
    print("获取属性的class的值:",tag["class"]): s+ A4 ]/ J  z  V
    # 新增  属性id  赋值logo* G5 H/ j# e" y, N  ?
    tag['id'] = 'logo'$ G4 u8 a  ^# y7 R( |% R
    print("tag对象的全部属性:",tag.attrs)
      K, Z) s, }4 j  N5 M# 删除属性
    * y) }+ N3 ~. y2 ~8 g1 s1 \del tag['class']; f8 U+ |0 _7 Q( u* K: ^; Z' p/ l$ j
    print("tag对象的全部属性:",tag.attrs)4 @! z5 J7 S3 p0 d$ a! W$ m( H1 T

    . R8 Y# Y4 [/ f" m
    9 T7 n- N6 ~- i- q$ s' c
      s7 n# F! A  c0 o. u2 H"""针对内容操作  (只针对标签,对属性无效)"""# Y: ?4 ]- C0 m
    # 获取title标签内容
    ) B% b- d" t( j8 _tag = soup.title
    4 K. b9 K' G/ x- ^# 获取title字符串
    . `$ B- ]0 k( W0 R6 q6 Jprint("tag对象所包含的字符串:", tag.string)& r5 c9 {1 m3 V3 M
    print("类型:", type(tag.string))
    % K  M8 |! Q0 J6 ~# 替换内容6 R  u* {. G7 g  l) H
    tag.string.replace_with("你好")' V) ~. z4 p* B6 D3 O: C: e' C& ]
    print(tag.string)# R; F0 j" t5 G( X0 k" G  c! a+ P: S+ Q1 h
    # <!-- 学科建设 -->
    - Y  ^' T/ o# D0 m  d# 获取注释文本内容
    & O' K1 n( e) t% M) R1 g9 cmarkup = '<b><!-- 学科建设 --></c>'1 c0 r4 ^0 W0 {- Z
    soup_comment = BeautifulSoup(markup, 'lxml')
    6 r0 a  v; K+ |" o% e$ l/ Pcomment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索
    9 L4 e8 s9 e8 C: h) aprint("获取注释文本内容:", comment)
    ! A: W: H3 C+ O! l$ A/ {* R# get_text()% [+ V- f4 l! i: y, Z! z+ ]
    print("title的全部节点:",soup.find_all("title"))
    . H! A/ A2 O2 o4 c# f. w( Q' b- k) Bprint("title的内容:",soup.title.get_text())6 ^: V$ m4 X+ `* H3 I" Q4 e
    """查找ul元素标签"""
    , e! l) r& Z7 [& ]9 j* i# class是关键名,匹配时后面必须加下划线_
    8 _1 M$ _! d) F3 @+ _9 y6 O# tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配
    1 P) U( w7 _1 T) o# print(tag)" {8 @& r2 E+ e! f+ w7 `5 l! X
    tag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配7 `2 v7 n& Y0 Q: C, ^" [$ e
    print(tag)
    0 Z! E2 {* [7 L9 b" g0 p- t! K& c# 查找名称为a元素的标签内容
    % N4 n. e3 o1 E; U9 T$ Ptaga = soup.find_all('a')
    - Y- ]- L% u& S4 K7 R% l" @for tag in taga:
    # _% u- I. q( \: _5 L  F( f3 J% [    print("查找名称为a元素的标签内容:", tag.string)' c* a7 ]) x& I9 K& J  w
    # get 获取属性信息  获取整个页面的img标签图片和src属性值
      E  e6 m; ^6 ]! ^9 q! J; f' ftagings = soup.find_all('img')( {- b4 k9 p' K2 \7 w
    print(tagings)8 c. g+ z1 a* N  j* }
    # 循环输出图片地址
    ' g8 b& ~5 F/ I  g- s0 ?; ?0 ?+ Ofor imgsrc in tagings:+ @# v4 g9 ?3 I1 x4 y% |
        print(url+imgsrc.get('src')). b  v! g" l! q2 v& @
    6 Q( O/ c5 {6 y* e; _
    """"属性只能做为参数,所有的操作只能针对标签"""' |! m1 L' H5 A) `5 E6 d
    ; S) m5 @& P; `+ t! d$ R& y
    etree方法:. B& K% e; ^8 X$ Z3 f
    导入库文件:& N6 K3 m, O) N; x

    * Z* S7 B! R) D5 t4 ffrom lxml import etree
    + H: l; D+ h5 y9 ?6 f1
    1 {# U' P1 F' X解析得到的response对象;
    4 r; Y# }- {$ Y+ J8 r7 ~: @% j, R9 K0 H& _6 l5 x
    # 设置response的字符集
    8 L' r9 w0 V& `9 i' {$ Lhtml = req.content.decode('utf-8')7 \2 W! `& j0 i
    # 解析对象
    % W+ r2 @2 X- }7 I7 I, [3 N$ [html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
    8 `. H" H+ h  w8 }8 [4 X) \1 m% i* ]8 Y) K8 ^3 ?8 E
    常用的方法:& H: r. \5 ]( B, `! Q
    9 u/ N7 E6 y/ x) ^
    + p9 M. m0 W; u( z; I4 t
    # 定位head节点(元素)
    * q+ a! D0 w8 U6 @) G, Sresult1 = html.xpath('head')
    $ z1 ?6 b+ i, i  z- w$ @print(result1)
    ) _' q+ B6 [) N# K9 N6 y/ M& l# 定位title节点
    / O+ \2 s# k8 [' jresult2 = html.xpath('/html/head/title')
    * B) O- Y- b% i7 _9 T5 C: Gprint(result2)
    # t) j" F1 _6 e% o$ m# f: c5 c# 搜索节点  title节点
    ! @1 n9 h! A; Kresult3 = html.xpath('//title')/ |3 A' _' u9 ~5 d0 B) c# f) q
    print(result3)% W) o4 G- L$ X  `3 |  {
    # 搜索title内容  text()得到文本信息* p7 u  M$ C$ L# y7 v9 p% n+ K1 X
    result4 = html.xpath("//title/text()")6 Z& C5 A/ m1 g1 o
    print(result4)
    9 A+ d$ X" x0 q( s# 搜索div节点
    $ q. I% Y3 Q+ [result5 = html.xpath('//div')
    6 x; c0 S2 i8 I, \& [( @7 W; Nprint(result5)
    % L: l$ P, v& `- Q1 g' n# L, W* y# 搜索div节点 并用class属性定位
    - n- ?: X- K4 O' Zresult6 = html.xpath('//div[@class="news"]')
    9 @+ q, \1 E0 u. [6 ?8 R; B/ ^- xprint(result6): j' ~1 R% Q6 V  z) T& T
    # 搜索div节点 id属性定位. V+ a: m! p9 G' m9 B$ z3 \, w
    result7 = html.xpath('//div[@id="news"]')
    * q. g. K" R& Tprint(result7)3 }. u/ U$ p& T) C0 X) f3 Z$ H
    # 获取列表span信息
    % s* d/ R) f* I6 ]5 l, U( _1 etext = html.xpath('//div[@class="news"]/a/span/text()')  S& n1 d# \- W" X+ _
    print(text)
    5 F, l1 u; d% D/ d4 [1 W: L: i7 K- n/ R+ I

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存0 |2 \2 l) e, q" D( E" N
    保存的方式有很多种:8 `- z7 y+ N# X% n+ `
    1、保存至文件- c$ h% \5 ~) [
    csv、json、text
    . t  g9 y; T4 e3 U. B2 ]% y8 d$ f2、保存至数据库$ V; e+ Y! b% T3 L
    MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍
    ) Q) _/ }. q. k; V# v
      B5 Z+ f" x+ G4 i. [! V# d9 x' T, i( H/ ?
    ————————————————4 T! {. M4 s# R
    版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。( t# M- J( I8 h% `
    原文链接:https://blog.csdn.net/royallucky/article/details/105930473
    $ D0 b7 P: I" h5 M
    ; P8 j7 H5 ?7 H$ [" e. e. m5 a3 N
    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-8-3 11:40 , Processed in 0.450869 second(s), 56 queries .

    回顶部