QQ登录

只需要一步,快速开始

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

    % ?/ g7 O1 e+ u. T' w9 p

    + j- t$ p4 u5 O
    % a- E, ]& o( N8 g) t9 O: {; [
    手把手带你5分钟搞定爬虫(聚焦爬虫)
    # V9 ]6 S4 C) V( ^3 v( f
    5 t; a& {' v4 h9 E+ I
    爬虫的原理
    2 g! Q4 W/ C4 j% ~* }2 U( e! M- z9 O$ Z
    对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫( a  S7 ]) i! c  O8 N! d0 _7 ]# t
    把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味
    ! W* i1 n' Z8 h3 r) F7 L所以说爬虫分为三部曲:
    4 E, x+ E: u  S+ p3 f* ^1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)5 u# ?# f: M/ K4 V2 v4 _
    2、去找到你喜欢的食物的位置(得到目标地址)
    $ k& m- j: I2 N0 G3、把食物搬回家去(解析网址,获取数据,存储数据)
    4 P! r' v- a+ e# l7 X# t它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)/ n. H) [) n/ N3 p; A
    a、导入需要的库 requests
    3 R- h1 W' |' z8 R' I) @1 |# N) v# _* m) L/ k+ m# N
    import requests
    - `. A. K) [1 p13 p( D+ V$ e% E  ^, E4 J
    b、明确你要获取数据的网址(这里以百度网站为例)# U1 N  V6 Y% F8 J0 u2 E! R2 T

    / Y0 r( d% p' ?- _5 A2 Vurl = 'http://www.baidu.com'
    ) u9 x" `2 C1 B+ _2 h1 g0 `1+ F3 `& _+ G5 X' N
    c、创建请求8 B5 S3 F2 I8 {& Z

    ; B$ F( K% \' Cresponse =  requests.get(url)8 l6 Q2 [( {5 d' H- K3 m0 |
    1  S- |! |" Q# R* U2 K5 f2 W
    d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
    7 [' d, M5 I( t* n! D) C# s' ]" b6 j" [! ?+ x  Z+ \
    print("状态码:",response.status_code)6 c0 C2 D5 z  N- O  A6 {6 g
    1! E1 t! L" u+ m, F2 K! z
    当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
      p( w" r" K7 Qe、得到网页源码4 b6 A; B# i6 r
    # L2 _# K; ?. x4 x$ X- q! _5 V
    print("内容:",response.text)
    : H8 S0 \; R8 G$ ]1
    * o4 g/ u1 m  o1 e. I/ g$ |7 D& ^response.content是response.text的二进制形式
    6 {& f. m  x, {# U5 P4 G/ f) n) [' p/ j* e. K7 t$ J
    至此,一个简单的爬虫请求就算是完成了。' I3 H8 ?! V3 z: `+ q! I" z* H
    当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据6 x' X$ F/ \+ g0 v" `% h
    f、解析网址
    / Y% v6 s$ C4 r/ B  j( O% u刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
    ) p/ E6 N" s) b5 a% W2 }; U3 zBeautifulSoup:7 z/ m6 r0 \& ]3 Q8 n% w/ @, N
    首先导入需要的库文件:
    " F0 I" k; e1 U, B, q$ }4 C+ k1 l) [+ [4 F+ _; J
    from bs4 import BeautifulSoup
    ! M6 S- B9 U3 n1
    2 T+ K1 a$ n( x, w" Q$ M9 w然后对上面请求得到的response进行解析:/ }4 c% _4 l& W; v) g& V

    " G' k- q& O$ Mhtml = respone.content.decode('utf-8')
    % [5 i& b! X7 `4 fsoup = BeautifulSoup(html, 'lxml')
    + P, N' a( x& W1 ?1* ^) Y( \0 ?9 A# }: Z8 A0 T8 y& c- a
    2
    / ?9 n! c1 J) B- @9 p9 }3 j; e以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
    & T5 w0 w- S+ m& g9 l5 S# 获取head标签
      U+ I5 r& P7 h7 b: G3 Nprint('head标签内容', soup.head)3 h$ i4 s4 z% c% S; |& H7 a* X
    # 获取title标签$ A: V% x' [- z4 w3 J/ @9 A" C- M: j' f
    print('head标签内容', soup.title). r; M* ]1 `- i! f  Q
    # 获取body里面的img内容
    ( `. G' v0 u8 k" N8 H# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签). X- O3 o- k) F) m
    print(soup.body.a.img)   
    ) P9 V0 x" O! ?  n4 u# 获取所有的img标签  使用find_all()搜索整个soup对象6 z; P* p. O8 J. ^" D  D
    print("获取所有的img标签", soup.find_all('img'))
    ' n; `  g) l% k2 D' q8 c: P# 获取标签中的属性src地址0 G5 j9 m. ^# x5 M) P; j3 S
    print("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值
      h2 }% H, C, V/ Y  w" X6 n% |5 |* M/ Q* g* M( X
    ; N3 t2 F& J& @
    # 获取soup的name! N# z/ l0 l) F' t- l' G& Q6 |
    print("获取soup的name:",soup.name)* W. d! t3 T9 ~6 v
    # 获取a标签名
      m* X: X& ]: ^5 K% _5 Yprint("a标签名字:",soup.a.name)  W) W4 Y1 P# i# g/ j
    tag = soup.a0 p# K9 z4 t' P6 O* S
    print(tag)) v1 L3 {8 S) Q
    # 修改操作  a标签改为b标签8 e; t1 S# `; X3 Q. l
    tag.name = 'b'   # 赋值后<a> </a>变为<b> </b>
    $ e8 v9 t* G: d$ x# 输出修改后的内容
    4 w; `9 |$ Y4 t, f! N. W% Wprint("输出修改后的内容:",tag)
    ( O2 o. g+ J2 d# \( ^/ r) W( ?* i! s# 获取全部的属性 attrs, j' g" r6 l& f. t
    print("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)
    0 ^6 Y: a% J2 z: \2 O- q7 e+ C2 k" l
    # 获取属性的class的值   根据键取值
    + Y0 v+ f' g1 J4 lprint("获取属性的class的值:",tag["class"])- u  Z) Y5 w) l" e3 b

    " X2 z7 j" O" H6 p( l  M/ Y" J  b# }# c8 {. }2 m# }/ \

    6 N6 o& w1 J: k: Z% v; q# d& K1 N" R3 I* u0 |" K' y4 f
    """针对获取的标签属性可以进行增删改查"""( G! _7 d  L2 y/ _) P3 w+ E
    # 修改
    0 Y% \3 A2 T- _* C2 Btag["class"] = "Logo"
    8 t+ Y. r9 o4 \+ R- y1 Jprint("tag对象的全部属性:",tag.attrs)" U1 u; i8 _7 Y+ t
    # 输出属性
    . V- A4 Z) V7 d$ `( jprint("获取属性的class的值:",tag["class"])1 y$ L. V+ t" w1 \3 R, L
    # 新增  属性id  赋值logo
    . C9 g. s! H: }4 `tag['id'] = 'logo'
    - E7 M+ B6 ]# {4 p* A; zprint("tag对象的全部属性:",tag.attrs)
    * Q) \! |9 I1 h; T0 `" f: k# 删除属性
    3 F& L, |' H) _4 pdel tag['class']
    ( Y  A# ^1 p2 e3 H8 h& h8 Oprint("tag对象的全部属性:",tag.attrs)
    8 `' g% [9 W2 q$ n1 T! R, w
    , O5 ~. {3 G' _# p! R2 u7 E& q6 W/ _3 Z1 H4 ^7 M) P
    2 J) Y1 l) ~6 a( A7 s. _$ X- A, k
    """针对内容操作  (只针对标签,对属性无效)"""
    4 C  c* x& v. N5 q# 获取title标签内容& a, |. ]2 ^% L7 i' N
    tag = soup.title
    ) Y0 G5 q  N% p/ V6 S* S# 获取title字符串
    ! h  q/ O* e: `3 y+ k$ x# \print("tag对象所包含的字符串:", tag.string)
    - g7 E; j6 S: q) O* n& y) pprint("类型:", type(tag.string))
    4 e7 H  w3 N2 ]# 替换内容6 y' ~) @0 F1 e
    tag.string.replace_with("你好")
    9 h( |8 a6 ~) I- b2 q  F! Zprint(tag.string)
    2 E( l" p- v7 c# <!-- 学科建设 -->- G8 u9 l" c8 b7 U
    # 获取注释文本内容
    : q: q3 P. f6 q' @) xmarkup = '<b><!-- 学科建设 --></c>'2 A, n1 X0 l0 W1 F$ ^
    soup_comment = BeautifulSoup(markup, 'lxml')
    1 D; v6 u8 G: \3 J- A6 V1 Ccomment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索% {8 Z+ S7 l9 h! g+ W
    print("获取注释文本内容:", comment)* m) Z+ ~5 l. X
    # get_text()
    . r& w, ~( [5 N2 Z  X6 o: pprint("title的全部节点:",soup.find_all("title"))
    & s1 r* Q3 z' ~/ L0 `$ Eprint("title的内容:",soup.title.get_text())
    ) h/ R. u# I4 H3 ^"""查找ul元素标签"""  M( L' U+ A# k" F) q1 b
    # class是关键名,匹配时后面必须加下划线_9 C. N6 u: s% R2 ]+ a/ P, E" D
    # tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配
    7 E2 y$ g3 G$ A, b3 K5 B; I8 Z# print(tag)
    4 t* [4 x: \3 e& ]tag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配
    # w* h5 V6 }& ?8 O/ W7 Uprint(tag)' a4 `3 R4 z4 Q( s; v
    # 查找名称为a元素的标签内容
    ! ~: y5 m& J- a8 H& E  itaga = soup.find_all('a')
    ( y4 C& ~; w& G1 Zfor tag in taga:
    . h" K4 X8 M7 N5 B1 N# M# c2 |    print("查找名称为a元素的标签内容:", tag.string)
    5 _* S. C& O$ H5 a3 o* b$ v* p# get 获取属性信息  获取整个页面的img标签图片和src属性值& O1 ^( B9 F! ?
    tagings = soup.find_all('img')
    1 s% {% C9 v, w  C5 x6 oprint(tagings)- R* A  k# @" w4 ]
    # 循环输出图片地址
    % c+ z4 o5 L% m  `3 k! yfor imgsrc in tagings:
    0 ^) K0 J6 \* z3 T! V8 e) n    print(url+imgsrc.get('src'))
    3 ]2 q4 Y: j4 Z. N: b$ d6 `$ N# N' R% h% f* g, X7 i, }7 b; ^
    """"属性只能做为参数,所有的操作只能针对标签"""6 E6 J0 A0 ]8 G% H' f/ X( V

    5 z7 b1 Y4 @( [( tetree方法:' m; g& E. p) c- @0 ~( {- i: L
    导入库文件:9 Y5 o# k' t$ Q! K% t0 L

    6 v  e' O$ D6 m0 r$ x; jfrom lxml import etree# x# d; C9 r/ o
    1
    0 F6 |7 I: J: N3 G) b解析得到的response对象;
    : l7 X4 ]: J& ?3 @- }
    ! r, H6 `! H8 C# 设置response的字符集
      B) t/ A& \% u7 `html = req.content.decode('utf-8')
      p2 L! C8 p& y& S: o4 f3 o# 解析对象
    " Y/ ~/ q) e  A0 K6 e1 d; R) Fhtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8')): r, ~# ~6 t9 l( @0 z2 W

    % W* g* j" `1 r6 V6 c% ^常用的方法:
    5 i1 b) L3 ~! z+ C
    + b) o/ Z* c" K' @. w- `8 {
    / C6 m# b' V6 r+ Y4 W/ r# 定位head节点(元素)
    2 T2 R) {8 Y8 ^result1 = html.xpath('head')! @# v1 ]  ~6 E7 Y, i7 @
    print(result1)$ T6 _" X. @, {; c/ g
    # 定位title节点
    ; j* e; W1 i: v' U; ?+ B, |result2 = html.xpath('/html/head/title')
    9 I  J* r( y" Kprint(result2)1 H2 g" |' h6 z7 @' n: A! `
    # 搜索节点  title节点& u: D9 m' D9 T; u
    result3 = html.xpath('//title')  O  `6 I7 a; f- A  E
    print(result3)1 q( u( x# C. z& r' X! n- V/ x
    # 搜索title内容  text()得到文本信息
    ; c$ E. t# T4 G! Uresult4 = html.xpath("//title/text()")
    " K8 |  x/ o# E3 \8 rprint(result4)
    8 J  r, w' M% ]5 B; n# 搜索div节点/ c1 B* o1 \$ A0 g" d
    result5 = html.xpath('//div')
    2 N2 X  }) z4 Iprint(result5)
    ) M' q% J2 F/ F" Q# E5 t# 搜索div节点 并用class属性定位
    & V- M) B( a& m) [3 Qresult6 = html.xpath('//div[@class="news"]')
    ! m: E1 Q4 D, V5 A6 [8 Qprint(result6)
    ( C! g! |+ L! ?# 搜索div节点 id属性定位
    * Z. U" H/ e! Gresult7 = html.xpath('//div[@id="news"]')
    ( O, {4 _1 C2 X1 Zprint(result7)
    - G# L0 t# G' b5 x$ R( D# 获取列表span信息
    7 q* k/ P) v9 _# b- I4 i# `text = html.xpath('//div[@class="news"]/a/span/text()')
    6 z' ]3 y: [  J* y/ ]print(text)
    " |- c; b( [9 y' ]8 C' t. a9 J+ ~3 c' o- t: T

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存8 e0 ~- N/ o9 f
    保存的方式有很多种:( E+ q0 ~: ^% i! L
    1、保存至文件
    7 q, J; D6 Y9 Y: ]csv、json、text& I9 v$ a) \0 n2 ?2 x5 [! \7 k
    2、保存至数据库
    ! O5 @5 z: C/ \0 N6 D0 G# }+ IMySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍
    " X1 h& \" C! [0 }; z, \
      f+ I, J2 i7 K5 F7 J! e9 T3 G9 \- r
    / C  o' n. w$ Y6 a0 ], z————————————————
    $ `3 B- C' }. X  h' ^2 n. h版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    ; V. {  c5 K: O, X6 P1 s原文链接:https://blog.csdn.net/royallucky/article/details/105930473
    " J0 j. H) q' [" r  K! \2 ^- k5 ~/ r! z/ g! \, O
    # ?) X. c* K  G0 v, T& i# Y
    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 05:26 , Processed in 0.424926 second(s), 56 queries .

    回顶部