QQ登录

只需要一步,快速开始

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

    # ^/ X1 _& ~5 z8 o  r* M/ m+ O
    5 p( E5 P- ~5 t

    / J0 F4 S7 {* M) B
    手把手带你5分钟搞定爬虫(聚焦爬虫)
    2 R/ x) |% j, q- E( y/ w
    : F6 O/ C  z1 K+ o% B0 S* H1 @2 u
    爬虫的原理
    6 K9 k# }% e  t5 W1 ]2 l
    - w6 h) {1 n4 E$ R6 |* Y7 _' o对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫, o* m) C4 m! i$ p8 s. G
    把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味, a/ E( ^7 s0 h  X7 U$ F
    所以说爬虫分为三部曲:
    ' H8 b+ N! Y) ?+ g1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)2 Y, U0 {/ E4 d& \& k' P% R& [! X
    2、去找到你喜欢的食物的位置(得到目标地址)9 }4 K4 y; a0 b
    3、把食物搬回家去(解析网址,获取数据,存储数据)" R+ @+ Q. `& M
    它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
    % S, g. _( c2 L9 a$ X; Ta、导入需要的库 requests3 W, z1 I) ?9 P" \7 \9 @" o

    # m- H- N; g' `2 y0 m' N% cimport requests
    4 k  M7 j4 p0 w1
    5 O# a0 T! }5 {' D" vb、明确你要获取数据的网址(这里以百度网站为例)( K! D6 z% o9 [5 ?/ h
    9 X4 u' P; S% X" Z
    url = 'http://www.baidu.com'
    + @) R; K% G9 ^8 P1
    ) k1 A$ r, A9 Z* L. rc、创建请求
    / J. y; x5 `( ]" ^% f3 ?) R3 P
    / ]8 O5 t$ X$ H  n0 P! }* x- k; Jresponse =  requests.get(url)2 M- T# D- v5 A3 Q+ \) `
    1
    0 i# p! q1 l1 k9 r2 R  D# ld、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)- I( g( ^9 p# N* s7 z+ c

    1 r0 Y* m7 c& a: F: Sprint("状态码:",response.status_code)
    9 v8 D& r+ [! f0 o) Q1
    : O5 s& b% Y# w3 e当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url* v7 z2 l) [9 [& K
    e、得到网页源码
    ) R5 u0 ?4 ?; g8 x3 b
    6 ^! Y' `3 l" s% J+ tprint("内容:",response.text)
    ' q9 q4 f* n; G$ u+ w13 E4 @% X( R1 {$ A+ w; g1 k
    response.content是response.text的二进制形式
    - F. [- ]( w. e- O
    ( z1 J& k7 Y' u, M至此,一个简单的爬虫请求就算是完成了。5 Z9 T  S# a- F: u+ R8 j
    当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据9 I, W* @3 O3 s& j6 b- t0 e$ `
    f、解析网址& Q! H8 h4 h6 R* z
    刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
    7 w+ b, |! Q+ g5 w+ L2 nBeautifulSoup:2 ~" g* r- c" N7 W& h+ F; @8 L' L
    首先导入需要的库文件:3 p+ F' g7 S* K& L

    ( d: S7 Y2 R8 X  c8 `% nfrom bs4 import BeautifulSoup
    8 _- c3 ]; N8 z7 B1. }1 C1 ?! T: J
    然后对上面请求得到的response进行解析:
    1 j$ l' Q  S. l# e' ]# ?' m9 S+ w3 |5 D0 _
    html = respone.content.decode('utf-8')) X+ q$ I8 v; ]! N
    soup = BeautifulSoup(html, 'lxml')
    ( ~8 ^6 A( T7 R$ s) ^1
    / q0 r% N, ]  j: N24 K/ C) g+ p* x
    以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
    / k# j( s  E4 r. ~# 获取head标签
    : [' Z! S, J( B& Zprint('head标签内容', soup.head)+ ~4 C6 l  O' Z% g. _' W
    # 获取title标签
    - ^/ h% G  D5 y* w3 zprint('head标签内容', soup.title)
    3 ~/ J$ ]0 C  ?! A6 X# 获取body里面的img内容4 U- k; n: q- V/ @- g; s% d
    # 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)# t% L- i+ N3 Z$ B  C
    print(soup.body.a.img)   
    ( }8 H3 h& T* Q" P# @# 获取所有的img标签  使用find_all()搜索整个soup对象
    # J1 W3 e. N2 K) O) [print("获取所有的img标签", soup.find_all('img'))
    0 @( `- R' Y3 ]! l$ B# 获取标签中的属性src地址
    0 M: i- [' n; h7 r" wprint("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值
    / G/ o2 D8 E  ?1 ~
    ( L$ k, `1 A" w, Q5 {0 Q2 u9 P, U9 z6 g& g, a# x* e
    # 获取soup的name( ?8 I0 [4 t  N4 k; c$ w
    print("获取soup的name:",soup.name)
    ' O0 j8 V& [; w% k: t9 p$ n# 获取a标签名! A( f* S+ ]6 x) y
    print("a标签名字:",soup.a.name)
    2 a4 X. _7 x, ?" Y4 T) s( ]tag = soup.a
    # a8 [4 |! W- w9 O2 }! wprint(tag)
    - i* K- \4 r$ t- M# 修改操作  a标签改为b标签
    6 K5 ]( F/ g  J5 Btag.name = 'b'   # 赋值后<a> </a>变为<b> </b>
    " d9 @. D% P2 |$ ^. z# 输出修改后的内容( w5 W7 R2 }* R3 d! l9 ?# |
    print("输出修改后的内容:",tag)0 m( Z+ D5 c* C# B* l8 C& R. S) R
    # 获取全部的属性 attrs
    8 |( ~1 @% l- C2 ?# sprint("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)
    % V' P3 T7 m8 x& f
    * a) ]; ]9 ?( A# 获取属性的class的值   根据键取值$ J+ j" T7 r% c( ~) i( Z* _
    print("获取属性的class的值:",tag["class"])
    ) j& C; r; ]* N6 l9 U6 Q
    / V1 K- s$ U2 T8 e  P. E9 [1 T$ C
    $ w6 @5 R1 T  ?
    / i0 C! T8 r8 y, m! B: v7 y) {, I1 {* l; }+ c
    """针对获取的标签属性可以进行增删改查"""
    / }% U1 C& P; U8 O7 {8 T# 修改
    4 H8 s+ C+ Z& S2 r: V) Rtag["class"] = "Logo"
    . k" @" l4 o* b8 s2 l# vprint("tag对象的全部属性:",tag.attrs)) n/ K+ F; S( \  f' V% W% q
    # 输出属性9 p1 w2 Q3 F/ l( ], y
    print("获取属性的class的值:",tag["class"])4 Y7 g# p$ F3 b
    # 新增  属性id  赋值logo1 T  q+ M0 y. \, q( N% l
    tag['id'] = 'logo'
    / C; a% I8 `# ], C0 S/ h- U, d5 Hprint("tag对象的全部属性:",tag.attrs)
    9 O, t0 Z/ X& t. g9 H# 删除属性0 V( |1 V0 z5 L5 C' d4 D
    del tag['class']
    ' _: L* z  |4 I$ Z2 f5 R! ~print("tag对象的全部属性:",tag.attrs)
    * E' J: {4 Y' l6 H$ W, Y6 e# H: X. K6 Y2 y% j) g5 v. c4 g
    * z1 X' b, {9 S& }. S
    - T) d0 Y0 I7 W/ T* {" I: v4 p
    """针对内容操作  (只针对标签,对属性无效)"""$ Z& |0 J) S9 [' ^) o: [& K0 |
    # 获取title标签内容
    5 J$ f- k8 J+ ^5 G, ~+ f/ Ftag = soup.title& L8 y- J2 h. b9 l0 ^+ X
    # 获取title字符串
    " e. r) ~! o# v: B( Eprint("tag对象所包含的字符串:", tag.string)
    3 a! W' J4 q5 J7 z2 r, lprint("类型:", type(tag.string))1 x$ I# [: h: {9 M3 M0 D& X- ^
    # 替换内容! k7 v# n4 [1 {
    tag.string.replace_with("你好")
    1 e: V! D' N$ G! O" F6 h" dprint(tag.string)
    0 ]6 @$ j7 }+ F1 \, S  A1 f9 O& D( v: g# <!-- 学科建设 -->
    % ~1 {2 s$ w; p  ]4 h# 获取注释文本内容  v2 i4 y5 n5 T. u
    markup = '<b><!-- 学科建设 --></c>'% K  N9 P5 ?* Z
    soup_comment = BeautifulSoup(markup, 'lxml')
    & j! S4 I# m1 S5 Qcomment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索
    ! M. I2 x4 P9 p( t6 ?7 B0 fprint("获取注释文本内容:", comment)# d8 z: C6 ~( q7 ]- Y+ s  V1 z
    # get_text()
    % U" {5 D3 z* v- H2 xprint("title的全部节点:",soup.find_all("title"))3 i9 O4 W( w. K' i: D* y  K
    print("title的内容:",soup.title.get_text())& l% V3 G4 @+ T( `
    """查找ul元素标签"""; I  }6 \, `! U+ s- d& B1 V
    # class是关键名,匹配时后面必须加下划线_1 v; E! X* H, q4 k! ]
    # tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配
    5 L; O3 Y" B6 b. o4 B8 o# print(tag)8 y. W* A2 `& s) h, E& B! [$ S
    tag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配! o& a; s3 u/ H1 q: K( Z
    print(tag)8 _/ {' {- R9 k8 J
    # 查找名称为a元素的标签内容# i* h4 }$ f6 \" U) R" @5 d
    taga = soup.find_all('a')# v4 ?; G  `5 ~- C- e
    for tag in taga:
    6 O' l1 z3 d" f    print("查找名称为a元素的标签内容:", tag.string)! m3 i5 q7 w( O" }1 r# V" K
    # get 获取属性信息  获取整个页面的img标签图片和src属性值) O( M- N# k$ V% A, h
    tagings = soup.find_all('img')2 x: K" i$ S- ?3 L
    print(tagings)4 [8 C& G* a8 D& Z. U4 }8 K
    # 循环输出图片地址; z! u- j. G9 y! `' I- R) J
    for imgsrc in tagings:; s9 Q- c' S3 X" M6 S2 U( D( p
        print(url+imgsrc.get('src'))
    * B) A3 a! _- A! M! w- t8 b6 t2 r$ t! {; w( q/ E, {& Z6 o' l- N
    """"属性只能做为参数,所有的操作只能针对标签"""
    8 L: d' X3 ?$ S0 ]6 z' R/ }- a# L% ?' S  e2 Y6 ?& b, b( R
    etree方法:$ |6 {% O0 A+ |! B( A. g/ y$ B
    导入库文件:
    1 N& c! F0 }3 R7 l: u5 m, @2 X% k2 z: X$ ~6 e
    from lxml import etree
    3 }% u- N8 n  I( |2 t: ]! `+ `( u0 {7 H1* E, {/ N/ ]8 a& K) v' Q7 g
    解析得到的response对象;
    6 c0 n0 B/ g4 @( i+ p, k; d& z% t, m  t& U7 N
    # 设置response的字符集- p7 w1 w6 K: m6 S, _0 h7 ^
    html = req.content.decode('utf-8')
    % X" R5 |% I6 O7 A# 解析对象
    " l6 W4 }7 |* S% b$ [' |html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))% L  j  `8 y9 q, A- G/ ?5 {+ n
    2 X2 _' w- T! q( U7 }  ]
    常用的方法:
    7 d# y5 x5 D8 h$ I* o4 [- _$ y
    ( M/ Z9 c5 o0 g/ U
    5 c# w0 z4 ]2 v1 x$ F* F' }. [0 H# 定位head节点(元素)4 t5 i4 j' y% a2 c: }
    result1 = html.xpath('head')
    & p' R( W; t. `6 f4 h5 oprint(result1)7 i5 X, ^8 m, Y, E) P$ {7 s6 _) p
    # 定位title节点
    ( U  h$ v' @" P0 E0 B( Q7 Iresult2 = html.xpath('/html/head/title'); V; n: a& \9 k4 y) ~( L
    print(result2)
    8 w/ o8 \, _$ Y2 i7 u3 T5 {# 搜索节点  title节点) r+ `9 W( [5 Q+ Y  }) ^
    result3 = html.xpath('//title')
    0 F, F# M- C( h8 I" Z  ?print(result3)/ V0 {$ `! m6 h8 F3 W$ P! R- s! J
    # 搜索title内容  text()得到文本信息
    + X) v, F, e0 k* g4 rresult4 = html.xpath("//title/text()")
    4 j- M" g  R. E! H- Cprint(result4)* x9 v) p. b+ n1 G) I7 H6 u
    # 搜索div节点$ M( `: O! ~! R
    result5 = html.xpath('//div')
    + t% b* y; {1 c6 @! Aprint(result5)
    7 k2 c: G9 C. r4 u9 c# 搜索div节点 并用class属性定位
    , t( V; p& g" h' \# [3 R2 eresult6 = html.xpath('//div[@class="news"]')
    2 C* D7 z" ~5 {# I( F) l6 p8 aprint(result6)- m  N, L9 S1 Y/ X, r. ?
    # 搜索div节点 id属性定位0 x* O. }$ h; R# Z
    result7 = html.xpath('//div[@id="news"]')
    ; ?+ z, S: o6 J8 n+ Bprint(result7)# g5 O5 n* f' l0 J0 P5 N
    # 获取列表span信息
    7 S: z# E. I. s. ytext = html.xpath('//div[@class="news"]/a/span/text()')
    ! U/ I: e3 [8 Oprint(text)
    $ S9 S! c5 w" ~7 x; y: U7 Y- ^2 o1 V8 |0 W/ k2 T2 F  F3 `

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
    ) c7 U2 D4 d% T. Y$ ?保存的方式有很多种:4 Q7 |; @# k' ?( G+ m8 A1 |
    1、保存至文件9 c2 c  C! _& ~! U, b$ i2 Y3 T
    csv、json、text
    6 ]+ t) q2 h4 E6 w5 T2、保存至数据库
    % q& z4 V6 S+ T9 g' }+ QMySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍
    & M- h: i1 _8 }. f! _& f0 A0 j) g8 o- {( D4 R4 s5 E4 b
    0 ~* L5 F9 F3 ?& P7 x* t
    ————————————————+ i, h  i6 G, c& E$ u
    版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。4 S9 j% P! d. T4 ?
    原文链接:https://blog.csdn.net/royallucky/article/details/105930473" q$ [$ t. @; R( i; c8 j
    # [. N  T$ A" {" g( j) P# b
    . h  U% C  D* q0 d" F" R
    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-6-15 03:42 , Processed in 0.570198 second(s), 56 queries .

    回顶部