QQ登录

只需要一步,快速开始

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

    3 b2 K2 K$ n, h0 s7 v. a, Y1 F
    8 G% J: A3 H+ H. T* E6 ~! q

      e1 ^9 d& o. y# S  N
    手把手带你5分钟搞定爬虫(聚焦爬虫)
    - B& }% R1 d5 k, z" m, y

    2 R+ S  {  a  s; B# r: L爬虫的原理
    * v0 n3 @' |" R& c4 _4 M" L/ t4 j3 S0 @, ?
    对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
    6 v4 }* m5 F. f1 F) s, Z把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味
    - \5 o2 W; C7 a/ l' Q所以说爬虫分为三部曲:
      h3 m6 c# j9 [! h9 c5 }/ n1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)
    4 ~4 D$ F7 e4 z; _2 {% ^2、去找到你喜欢的食物的位置(得到目标地址)
    5 d' u6 b, ?$ m1 V9 A! {" y3、把食物搬回家去(解析网址,获取数据,存储数据)3 k5 A' A  u8 Z5 _" S
    它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
    * z7 S9 P% E6 E7 ^& da、导入需要的库 requests% O1 z2 r# o0 M3 _

    ( @+ l- t& N9 N! Bimport requests
    - k& N/ \9 n# w$ F12 {+ W6 n9 ~4 E- G: D
    b、明确你要获取数据的网址(这里以百度网站为例)/ q6 c0 e  y# R) c* c: t
    ' u! M. J6 Z( ~& [' v- R- m
    url = 'http://www.baidu.com') f: v$ u6 l) \
    10 n2 ^+ [; }& ]
    c、创建请求
    : y; n# F0 J) |( D, X; Y6 I+ b# ]3 \
    response =  requests.get(url)
    # `' ?8 ?$ X# u; [* ?& V) Y% X  N. H+ J1
    : \0 K; b  }* S4 d5 t+ Jd、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
    4 [! o: @6 g7 w1 e' P, S! N0 Y
    6 C) G! l& L! n$ pprint("状态码:",response.status_code)
    ( D7 E2 Y" W' l0 Q! i8 i% W1; s0 _) Q  Z# x! l& L' p# v# m/ T
    当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
    5 a3 N0 i9 A6 d* p) fe、得到网页源码
    & e+ w; x9 L- q! s' |
    ' l: Y/ u( k2 d0 H% N2 B! {; p. Nprint("内容:",response.text)
    / g5 J9 b; E! g0 L8 q1 K1" H' f' q5 ?* ]% O
    response.content是response.text的二进制形式( J# Z. A0 r8 U

    4 I  c0 L' n: l* x: L至此,一个简单的爬虫请求就算是完成了。
    # B9 N/ H( F* D! {! U当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据( s" e( R4 t8 s  e8 E0 S
    f、解析网址& l$ z0 D( [) }+ d8 T7 u, _* |
    刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
    4 @6 g! G0 o2 L3 o5 a4 ]6 QBeautifulSoup:" q4 {. p- V3 t0 ~1 l
    首先导入需要的库文件:
    ) c" ]' i& q5 L; T% D% C* `
    7 E  B7 M) W, q: \# B/ vfrom bs4 import BeautifulSoup
    ! @0 W$ K4 T  y, R) |1 a  a1
    7 H- d8 q2 [5 {然后对上面请求得到的response进行解析:) E0 S/ C; n. j8 V3 @

    2 A2 }' S+ J( zhtml = respone.content.decode('utf-8')# [8 w; U- D7 t
    soup = BeautifulSoup(html, 'lxml')& c& y# d- j5 X$ I
    1+ _& D# v4 W: e" O
    21 d' L1 I2 b- y% z8 r- O3 w$ Y
    以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:1 y/ V4 F- v1 D' a: N
    # 获取head标签" a, _+ B1 C2 {/ B7 m# O
    print('head标签内容', soup.head)" Q7 W" S* f3 Q7 z8 I) ?4 p
    # 获取title标签  }* a5 T) T, p) T: _
    print('head标签内容', soup.title)8 p5 l& d7 u/ e+ z
    # 获取body里面的img内容
      y/ _3 N+ q' [  ^# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)$ K8 K* K$ A$ y. \# t& e
    print(soup.body.a.img)   
    3 Z* n2 }% D: g, M9 J8 r& w# 获取所有的img标签  使用find_all()搜索整个soup对象" G" @" t( c  s4 J) ], u7 H
    print("获取所有的img标签", soup.find_all('img'))
    ' A; ^2 l& D9 S( P% m# p4 `4 K8 _# 获取标签中的属性src地址0 ]6 u% A# w9 k: r9 b
    print("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值
    # H- c& j- d6 n; p' u7 n0 Q
    & n3 Q8 o9 z3 H/ c  c% s
    5 m+ T7 N( l5 w* m% b" ~; E# 获取soup的name" _% |. _. Y. n# Q7 H
    print("获取soup的name:",soup.name)+ b, S- i+ E! W9 e
    # 获取a标签名
    ; t' ~( Z  m4 _+ iprint("a标签名字:",soup.a.name)
    3 L1 G* c& P$ d! r- Jtag = soup.a2 X) C1 r3 ]" H. r+ U4 w+ s+ x
    print(tag)
    ' J% d! O( f# D# 修改操作  a标签改为b标签- }9 ]- Q) R9 e( j& ?* g
    tag.name = 'b'   # 赋值后<a> </a>变为<b> </b>
    % U) z, z. R0 h4 l/ w: c6 |# 输出修改后的内容
    + T6 w% D" f& }  Oprint("输出修改后的内容:",tag)! w; c' f0 C1 L! Z, c4 f$ @/ q
    # 获取全部的属性 attrs  r  L1 S  Z+ {) u
    print("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签); R8 Q+ B" c! B- g0 ]8 V
    ; I4 z; Q: u3 ?8 ~5 p0 N9 m9 W
    # 获取属性的class的值   根据键取值0 l5 q8 L5 y2 t; u7 U9 z
    print("获取属性的class的值:",tag["class"])$ p- P( h7 a* a! w6 |

    # W  i: m) i/ g1 i
    2 r1 u7 V) B2 o1 {# R
    9 D# w; K+ M$ }6 x$ q, T4 f: C5 T; K- a4 M2 Q
    """针对获取的标签属性可以进行增删改查"""4 g4 Y3 V  Q* ^
    # 修改
    3 l+ U9 i" `# x/ ttag["class"] = "Logo"
    ! @8 C2 c$ H! y4 e  h# Eprint("tag对象的全部属性:",tag.attrs)
    3 x5 V# P% Z" G5 C1 |. o& Q2 ^# 输出属性
    7 M& p9 P( I- q: {7 B. Z5 _print("获取属性的class的值:",tag["class"])3 X* x, j' Q* V7 g
    # 新增  属性id  赋值logo
    6 K# G4 |9 A2 s/ _8 mtag['id'] = 'logo'
    % `* U" Z; Z# g; g3 G5 qprint("tag对象的全部属性:",tag.attrs)* y* o0 m0 ^# e$ `" E( D+ h, _% V
    # 删除属性- a( G# U4 B; m& G5 j
    del tag['class']
    2 h# w4 W4 p) G7 m  sprint("tag对象的全部属性:",tag.attrs)1 b( e9 [; X: d1 ?& ?4 O( S7 n; I
    ' I8 q2 T! O  Y6 F" [  y

    9 A7 O, X# X/ ]6 B# q+ v7 h
    - y+ D* \, y& L% N9 F3 u0 b"""针对内容操作  (只针对标签,对属性无效)"""
    , e  ^) p) f/ q$ B* b6 x# 获取title标签内容: m8 S" M. W  V2 w; ?
    tag = soup.title& R% x" H, p, J) t4 r! q% }  i! [
    # 获取title字符串: r. D% q3 p- \- A
    print("tag对象所包含的字符串:", tag.string)  f3 I5 [* ?2 @0 O
    print("类型:", type(tag.string))' A/ A4 D! p1 U
    # 替换内容
    ( n7 l! `" T; n! R: otag.string.replace_with("你好")
    4 R2 `. l5 ]- e6 c, c* Uprint(tag.string)6 U: P; H; f( V9 Y9 b) \3 U: z
    # <!-- 学科建设 -->
    ; J7 k* p$ A" D2 o- p4 e  y; j1 I3 k8 {# 获取注释文本内容& Z: r. F0 ^8 n2 k" L
    markup = '<b><!-- 学科建设 --></c>'
    ( ^; Y; ]. s  C' Qsoup_comment = BeautifulSoup(markup, 'lxml')
    ( r; U& E0 A# fcomment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索
    ! ]5 y* U! M4 Y: w7 B. m# t: qprint("获取注释文本内容:", comment)# o' r% l$ x" z# w$ H) {
    # get_text()1 }( I' E& e8 I0 U4 v% f
    print("title的全部节点:",soup.find_all("title"))
    : Z' q4 s# f  X% P, rprint("title的内容:",soup.title.get_text())
    + n' z' l6 Q  S; n% }"""查找ul元素标签"""  ^$ G. m# B; D# D, D8 @
    # class是关键名,匹配时后面必须加下划线_
    # V$ h" a$ b, R( S- c5 L# tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配
    & H2 u  b/ H7 v, L% y# print(tag)
    ; l% X. I7 t' t. G$ C1 c# rtag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配) A+ N' ?- g+ J4 g
    print(tag)
    # L5 H# h* m: ~* Z  o6 u# 查找名称为a元素的标签内容0 c( f* R. q" P) F; d: `0 e' e
    taga = soup.find_all('a')
    * H2 d/ I, V" I# o2 Wfor tag in taga:9 w# R- v, C. I6 @( M- f2 m. e2 m
        print("查找名称为a元素的标签内容:", tag.string)1 q0 _0 @. C' e/ `! F4 b) `# O2 A
    # get 获取属性信息  获取整个页面的img标签图片和src属性值  z" T+ d/ j) Z
    tagings = soup.find_all('img')
    ( Q! D  ^" M% a% T, `print(tagings)# {3 _0 R2 l3 K. I3 w
    # 循环输出图片地址
    : B9 [; y" }; n. X, jfor imgsrc in tagings:2 T- z: Y2 }. Q
        print(url+imgsrc.get('src'))8 i" @' |8 T' r' _  E

    ! D4 _& p' J8 e5 _. N""""属性只能做为参数,所有的操作只能针对标签"""/ B  N6 i- q/ e4 Z/ _% s
    ; G3 [2 Y! B5 U7 T% J; Z
    etree方法:5 P5 G6 M2 f( v+ R' U
    导入库文件:* `: `$ B. b( P2 j" \
    9 F6 O6 g4 U9 b% _% [9 V
    from lxml import etree2 f) a  W  `9 s  H, @) W
    1
    3 \+ A: _8 M( z9 ]6 B解析得到的response对象;
    * `! R+ @* z6 R
    5 G1 R1 E% N7 E$ q0 q# 设置response的字符集
    3 I/ i' f5 ?0 g- ^html = req.content.decode('utf-8')/ d$ \6 |+ {+ G! f) r: q
    # 解析对象
    4 u3 d4 E. c7 }/ J) J( J; Ghtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
    . W8 n4 y1 t; X, e0 n1 [* d) H
    0 l. Y7 ~7 Y) s/ U, ]2 c1 |常用的方法:
    + y3 O) b2 A$ s, p
    ) m' s5 m  i/ g3 m' V' G' B6 s5 E6 L6 B# i& X0 j
    # 定位head节点(元素)' M$ N1 @! L4 N
    result1 = html.xpath('head')1 p  x& u' E2 C1 N6 I; _
    print(result1)/ S3 ^6 z8 ^- r0 |; ~
    # 定位title节点# j9 g5 Y* M: j4 x% l  q
    result2 = html.xpath('/html/head/title')% b6 r/ G& C/ P1 s3 w
    print(result2)
    ' y; y9 C- t' U- I/ O% a2 ~9 W# 搜索节点  title节点6 d6 Z, ?4 F; t7 M3 W. Q! Z
    result3 = html.xpath('//title')
    0 D' g/ h5 T+ B  oprint(result3)
    - C! R% I/ M; p8 r7 G* a8 S# 搜索title内容  text()得到文本信息
    4 D  E& z3 l( o: I& `5 {, Tresult4 = html.xpath("//title/text()")/ W9 Z2 L* ]5 ~$ Y
    print(result4)2 E: R8 c/ `: D; W0 ~0 M' T3 E
    # 搜索div节点1 G& @8 r' U' I$ p# o/ Y! [
    result5 = html.xpath('//div')
    ; {9 g9 N* b( Eprint(result5)% T: c5 V* }' M" O+ v& l" s+ i! d
    # 搜索div节点 并用class属性定位  L: o6 C! ~2 f! O, w4 |! ]$ D
    result6 = html.xpath('//div[@class="news"]')
    % L2 s3 ?# j- N8 }# \4 tprint(result6)! {8 L* Q6 b& Q6 f/ x  S6 a- ?  K9 U# [
    # 搜索div节点 id属性定位
    - T4 l; G: S$ r1 F* k. J8 g- z" hresult7 = html.xpath('//div[@id="news"]'); @8 b8 v1 R3 V1 q. u! h
    print(result7)
    / J; g. w: k0 n4 N# 获取列表span信息
    & @( I% D* C  F" ftext = html.xpath('//div[@class="news"]/a/span/text()'); m+ [) G1 W; Y& @' P1 S, b$ R
    print(text)# C  p; e5 H/ g, f& c* o' @0 V$ ~
    9 j  J, Z- S0 ]% G) ~! {& v, O4 C

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
    - h8 e  x3 g' ]% V# r% O* l保存的方式有很多种:: ]8 t& }/ O# ~  l: P
    1、保存至文件
    , A/ C, _; U/ U! k& M7 y3 hcsv、json、text
    $ D7 g0 h: U2 D; R$ o2、保存至数据库
    # Q8 A4 w& t1 Y" r  KMySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍$ x% W2 Q" p) [. g2 e& u, H' q

    ( y$ n8 o- R5 ?% m" B+ \, p+ ~9 L
    9 I! C+ C0 l+ Z, }; U————————————————/ N3 X2 F# j7 ]# ?7 n
    版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。5 g9 }/ W, j1 d3 @6 K4 a
    原文链接:https://blog.csdn.net/royallucky/article/details/105930473
    1 A% n1 Z. `. E/ h1 `
    . F5 E: u( F0 [: q3 ^$ Y. O& i: T# S
    * J% k6 w# q- n0 B7 P9 t
    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 02:41 , Processed in 0.444473 second(s), 56 queries .

    回顶部