QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3665|回复: 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
    + L/ v! u- n/ I
    , H4 @$ b' Z* M+ y5 w& C

    : x2 m8 Z6 U2 Q3 B0 X, v
    手把手带你5分钟搞定爬虫(聚焦爬虫)
    ! O: j" ?# h1 U6 c4 c0 D
    / X$ r, F0 n9 D+ Q6 z$ g2 a/ p  |9 Q
    爬虫的原理
    ' ~5 F9 v4 _* E3 R% `% r+ r( R/ v/ J
    对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
    * E$ D4 S2 ?1 r& t) m3 _+ L% p把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味: @$ D% L' F7 H: `8 }; e0 W# A
    所以说爬虫分为三部曲:- B* x9 G4 B! r, H# G8 F8 \
    1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型), [/ Y! y1 [, x0 c9 A, c2 S
    2、去找到你喜欢的食物的位置(得到目标地址)9 m, g( g, @8 u/ @$ ?
    3、把食物搬回家去(解析网址,获取数据,存储数据)
    / t4 d$ o, z- \8 o它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
    0 M; k' R  j! I, Na、导入需要的库 requests5 B( t4 N1 C! H2 A. S/ \" R7 ^

    8 b: j  g$ {" L. D1 Timport requests
    , Z; k* H9 n% Z1$ B- N$ \+ M) o% c! g+ h3 j* \7 u
    b、明确你要获取数据的网址(这里以百度网站为例)
    : N8 |! a' O. s$ o% g
    ( u7 p. t( f" C9 E4 Rurl = 'http://www.baidu.com'. {7 L! y( ~: o: v" j
    1' [9 E' c& x. t1 u! z+ j
    c、创建请求! \0 o" Q: F6 a2 g3 U, u
    0 b0 I  K0 i5 I4 b" e
    response =  requests.get(url)( X/ e$ ?- V1 p' x2 [( |8 r9 ^; E! ^
    12 g) r1 O, e) r" d1 r
    d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)1 c$ O% w) b4 Q; h) N* B0 m

    7 R/ L5 \  i; Z8 g9 X- cprint("状态码:",response.status_code)) F, y& G4 X& s, d2 J+ W
    1. A' s2 d$ L! ?& Z* a! e5 n' W( u0 b
    当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
    9 Y% M* \' A8 @7 q/ ye、得到网页源码0 G% ]* L% `& v8 c3 H. j8 B  [' V

    / x- k+ q7 P- rprint("内容:",response.text)+ G; X3 ]9 b9 T3 ]: h
    1; E: g! I& |! t( p
    response.content是response.text的二进制形式
    % V9 B' Q! s! X% ^1 n5 e3 T  ]7 |- q/ t
    至此,一个简单的爬虫请求就算是完成了。
    ) H  B3 A- P+ z+ O$ U6 s当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
    7 T$ k) `) G- J4 Y+ T& b% wf、解析网址! H) _. z' I! Q
    刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
    ( t8 {5 L! [; ^4 {9 ZBeautifulSoup:$ z- E9 }! W9 j3 J
    首先导入需要的库文件:0 C& g/ U. `. A/ A  ?7 R* d

    3 u& A- Z8 H! Q" ^0 Yfrom bs4 import BeautifulSoup* u8 j8 n0 x9 n4 z, F
    1
    3 f& O( W  e, `' t% a  w; v* X然后对上面请求得到的response进行解析:
    ( A/ A+ u2 a5 y( L& |
    3 Z- R( F2 w0 E) `! N) R  k) ^html = respone.content.decode('utf-8')' }. n% T# {: A2 V/ W3 p! Q: u
    soup = BeautifulSoup(html, 'lxml')
    ) k3 ]7 k. b1 Y( E* G8 h' g* N11 W: _1 r. f4 ~) y- Z: B. P& `* m9 H2 b
    2
    & x- ~& G: e& P以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:8 p6 ^$ W, C1 R( T/ F& a
    # 获取head标签- [0 d1 m1 O6 E( K1 Y
    print('head标签内容', soup.head)2 H+ b1 |! P- {# v$ W
    # 获取title标签
    3 M6 s9 Q% {8 W2 Uprint('head标签内容', soup.title)
    % ]. P5 L0 V  c  h# S5 Q# 获取body里面的img内容8 p; i% b4 ^, Z  d+ E
    # 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
    5 r1 b1 F4 ^2 }4 `) n! w) Hprint(soup.body.a.img)   
    % L- D* x2 n+ J( ?9 v! ~) m# 获取所有的img标签  使用find_all()搜索整个soup对象# v  B# q) m. @( B* W4 d$ O
    print("获取所有的img标签", soup.find_all('img'))3 p0 ~- E5 F& L& v9 _1 j) y
    # 获取标签中的属性src地址
    - ?$ b: j( R- q. U: e3 ?: A; Iprint("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值
    , r9 Q! l* J8 F( r6 q
    # e/ M# }" V1 x& W' f! s' _4 N% M
    % D1 n3 h8 V8 u% j( _+ V! U& K. a# 获取soup的name0 O; h/ o" [2 Y0 K9 _$ u
    print("获取soup的name:",soup.name)
    8 K& P* f4 p: L, W8 G  m2 f# 获取a标签名5 P# d! F) }, X3 r0 V9 a  \( a
    print("a标签名字:",soup.a.name)
    ! p8 T5 j6 ^3 ?2 D9 q9 Utag = soup.a
    9 z. O- }1 p9 W. H; K# Iprint(tag); q$ _% t$ V8 Y2 D, U
    # 修改操作  a标签改为b标签) S; ^/ I( r# e1 ?7 K
    tag.name = 'b'   # 赋值后<a> </a>变为<b> </b>
    7 B, q$ M- F) I" q2 ^- ~# 输出修改后的内容
    . _6 P# N( D; q7 Mprint("输出修改后的内容:",tag)
    0 S5 l; ~- B; E3 r# 获取全部的属性 attrs
    ! ]9 _  u2 Y6 o! }8 z: j' cprint("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)
    - R! _, d8 r; I/ K5 k' m1 q1 m9 t. q6 w7 [1 L' p" a5 Q
    # 获取属性的class的值   根据键取值
    ! Z1 e3 ^! M* n4 ~2 L- uprint("获取属性的class的值:",tag["class"])+ _( u  c( s, J/ K* f7 v

    8 z2 k; y8 z. w1 q  E( {" Y
    6 |# f" d; R$ L; C
    & }- q# {. |: l
    4 v3 f3 c5 _8 a"""针对获取的标签属性可以进行增删改查"""/ c, x2 r5 W$ m; D. P
    # 修改
    . ^) g& E. B! D3 }$ C! X( V8 ]7 {tag["class"] = "Logo"$ O! u2 k$ s! U) r. D7 j
    print("tag对象的全部属性:",tag.attrs)9 m0 y4 [3 ]6 v1 K
    # 输出属性
    ' T* |. D7 B, p0 j& sprint("获取属性的class的值:",tag["class"])
    ( O5 z& f" l% r" m5 ?# 新增  属性id  赋值logo
    . y( k1 I5 d" d* E; htag['id'] = 'logo'( k0 [9 g4 a+ T, u( x
    print("tag对象的全部属性:",tag.attrs)
    * I: e, g4 U# m, m+ x7 A1 D8 L+ ~# 删除属性. I0 t, c: O4 A; }1 R! X! {
    del tag['class']
      Y) ?  s3 W. a4 F( @print("tag对象的全部属性:",tag.attrs)1 _  |1 m3 k2 d* I* U
    . J- A" _6 H" ~# Q" Q4 }* d1 f

    ) V7 U" ]6 m' P& H3 Z1 n+ Y! F& g% y4 S1 ~2 E! x/ u8 o" d- F
    """针对内容操作  (只针对标签,对属性无效)"""0 ^4 C3 j/ e! Y
    # 获取title标签内容3 m) j  J( L3 k+ i
    tag = soup.title
    ; ~9 U/ y' m: T0 l$ h# 获取title字符串
    - G. H! W8 o8 d" p9 Hprint("tag对象所包含的字符串:", tag.string)
    ' U% L) T  N) m3 ^' ]( Iprint("类型:", type(tag.string))2 e% x" E# t8 ]8 c8 M( s: _8 c( K
    # 替换内容& H1 S& U; R7 q1 z5 C+ Z
    tag.string.replace_with("你好")
    ; F/ t  l$ q( qprint(tag.string)* z0 V' B/ e8 E
    # <!-- 学科建设 -->7 p, V0 J4 j. \( }2 g
    # 获取注释文本内容: w, |& x& g- Q0 ^
    markup = '<b><!-- 学科建设 --></c>'
    2 A; N- X  y" o8 \4 I6 ^soup_comment = BeautifulSoup(markup, 'lxml')
    / L2 a6 G* N, W6 C8 o) icomment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索
    , E; C/ w  n" x, x% Cprint("获取注释文本内容:", comment)
    ! D! l( J0 M: O6 j# get_text()( V' c3 }: p/ e$ Q1 @# l0 N6 {
    print("title的全部节点:",soup.find_all("title"))% K, F4 D2 Q' B: ^' h+ \
    print("title的内容:",soup.title.get_text())
    ' Y1 G0 Y8 U4 G1 ]"""查找ul元素标签"""
    , l. R0 w% o$ x1 R- V7 C, Z5 Y: D# class是关键名,匹配时后面必须加下划线_$ D3 u# Z. Z9 @( G+ d) v* W
    # tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配
    * F8 D6 ?$ w5 l& y7 i! s/ X+ i4 G# print(tag)
    2 e0 r9 B% `5 |* x1 Rtag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配7 N9 f  c+ K4 M7 t8 E. }, z
    print(tag)
    : o6 B0 }4 B  N2 @8 e# 查找名称为a元素的标签内容8 l0 o% V+ C+ f! y& {* D
    taga = soup.find_all('a')" U: H- Q# e/ _) n' |
    for tag in taga:
    % q2 t7 _% H1 H2 ~' @; @  y    print("查找名称为a元素的标签内容:", tag.string)
    : _! g+ H; Y# U& a" Q$ Y# get 获取属性信息  获取整个页面的img标签图片和src属性值' }/ Q5 n2 S5 |' c
    tagings = soup.find_all('img')
    ) K2 D3 T7 f; Z) nprint(tagings)
      @! J9 @  D& k! N7 d; e: U# 循环输出图片地址! J1 |% M9 \' _1 z* K* i
    for imgsrc in tagings:& _3 O8 D1 \: B1 @
        print(url+imgsrc.get('src'))9 ~& L6 w6 r4 v
    + a, w2 J' G) b# Z: l$ b& W" B" C0 V
    """"属性只能做为参数,所有的操作只能针对标签"""
    3 ^( z+ @' i0 d. L4 D0 Z  e4 h' c4 l# A5 ?  `3 m0 o
    etree方法:! O7 Y) g) h0 w. e- s# s
    导入库文件:4 s! P: I5 Y2 y! R0 k; l6 A

    8 ?) G/ [/ P7 @3 b, ]; E6 mfrom lxml import etree
    & x) f" U$ _: r' A8 z1
    , [; Q7 B1 x4 v+ w解析得到的response对象;+ v3 X/ g2 v4 @: s# Z5 k
    2 `) n  m- q! H1 J- z/ \6 X4 o
    # 设置response的字符集& z" J9 t" T" I* V) g- @# q
    html = req.content.decode('utf-8')
      A7 A6 I6 A- \- P3 ]# 解析对象
      X5 V. [3 l  fhtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
    ) P' j# t# i7 w8 u
    " z* z# H7 w& s常用的方法:
      h9 F+ B1 a( d6 z9 }! y9 s' g
    / A3 N) p0 ~& s, ~3 o. W& T$ R' w0 G* c
    , B( a0 b$ Y8 X' W: F# `6 U# 定位head节点(元素)
    8 ?3 _& U; b0 V# w! m4 J+ b  n/ ?; xresult1 = html.xpath('head')
    1 l2 z' l' l& ]) `5 N4 Pprint(result1)
    + k1 B/ `7 N* Z8 @- x) A  r# 定位title节点4 V; L# w% u+ p
    result2 = html.xpath('/html/head/title')
    9 w. s  |) r+ h. u+ ~  Kprint(result2)
    & U! w' Q6 |% p& k  s% [/ V3 M# 搜索节点  title节点. ^( E6 |7 r0 `) P7 e# L& M
    result3 = html.xpath('//title')
    , c9 b0 Z' s3 N( _4 @- u) ]print(result3)
    " L3 i0 P0 }: J9 M0 W1 r. b% Q. u# 搜索title内容  text()得到文本信息2 j- T) s" L# K# ~! |8 Q
    result4 = html.xpath("//title/text()")# y1 Y+ N8 h/ T& T; s+ n& S! U! W
    print(result4)1 J" Z) U3 A7 D
    # 搜索div节点. O5 U( Q$ y6 ~
    result5 = html.xpath('//div'): y$ K6 ~0 J" a
    print(result5)
    7 L1 p' [' k+ A! j( p# h. o9 A8 _' H& a. B# 搜索div节点 并用class属性定位
    6 h2 Q+ U* f$ Hresult6 = html.xpath('//div[@class="news"]')
      V1 O  d3 x! _% ?$ Q/ V" \# K  r  I& s* |print(result6)
    & m6 D6 V8 i+ O0 s# 搜索div节点 id属性定位% A$ u+ L& n+ n& N' v# Y6 E' w
    result7 = html.xpath('//div[@id="news"]')0 z2 |& w6 K* |" X" z0 Y
    print(result7)- j' k* a  e, D7 R( U2 s3 w
    # 获取列表span信息
    / j6 B2 f: b1 z1 mtext = html.xpath('//div[@class="news"]/a/span/text()')# Y9 l% e- ]; v
    print(text)" J3 z( m% B0 W* I2 ^" ~
    2 r# W# O* F' {7 c* t

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
    ( x% i6 [- ?% @4 C; ^: N8 q保存的方式有很多种:
    6 @, @2 X- @1 t& u  b$ N+ Y8 v* K1、保存至文件
    $ D2 f  E7 |2 m% s6 Pcsv、json、text. q7 V0 D5 D7 Y5 y% G
    2、保存至数据库
      `4 j2 M+ ~' p( w9 H& tMySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍
    8 }5 h1 X+ F: ?4 l8 ~0 D
    ; Y3 t/ f0 g0 Z; C+ G
    9 n" T3 b7 ^( L! ]8 W————————————————
    ; S, N$ f% S' ^) H9 |" ~1 S版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。7 Y3 w! a, k: a
    原文链接:https://blog.csdn.net/royallucky/article/details/105930473
    $ K. f6 \0 W! `2 d1 g) \/ D8 L
    , H" F: w7 u) X" K9 |
    / ^5 {2 k* H; W& f; l& V1 h/ v9 S
    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-16 22:42 , Processed in 0.437872 second(s), 56 queries .

    回顶部