QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3660|回复: 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
    % Z) L* I- T# f6 R7 X6 R  k

    # f9 G( q7 }) `6 n  @

    ; w0 X; ^" F- R* g9 G: g/ B
    手把手带你5分钟搞定爬虫(聚焦爬虫)

    5 c# ]* R4 g) S& ]: T, O* G4 p) T4 G7 F' C
    爬虫的原理
    3 y- [, E( H8 C6 \  T5 ]$ d
    : c1 ]! e/ V( l6 ?2 j2 \对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫1 g! E! K3 A- j+ m8 G( s6 u$ Y8 u
    把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味
    ; S2 _: {; [& Y0 a3 F9 E/ s5 s6 y$ J所以说爬虫分为三部曲:$ c+ H/ ^% D+ j6 [
    1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)) W; ~6 s" k5 R/ H4 q9 P! k
    2、去找到你喜欢的食物的位置(得到目标地址)
    . n: p# J( ^  A4 |9 H/ s$ {3、把食物搬回家去(解析网址,获取数据,存储数据). h+ g$ o8 L0 f+ q6 M
    它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)1 e7 a" z% D% N" o) e% h, {2 F2 b
    a、导入需要的库 requests
    9 }/ y# V3 D- }
    ; L1 {0 K# Y' O. j& G  @/ x2 k2 [import requests( I5 h  e' P6 a6 f9 f
    1, x! u9 f7 C+ J6 J# c/ O/ {" F; n
    b、明确你要获取数据的网址(这里以百度网站为例)
    & Q9 P0 [- N; U+ V/ Y4 s$ X, m# U8 R
    url = 'http://www.baidu.com'1 d' A4 i2 c% y6 M
    1
    ' d6 f" ^- _1 e6 a/ i( Fc、创建请求& e; e3 l7 o" U  f4 \

    9 n$ e& k# t# @: tresponse =  requests.get(url)
    2 _  Z3 G/ o' P3 b; V1
    ( f* F7 Z& F6 |: _3 Fd、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
    ; E  q$ [8 b/ P: f" ]% B; a* H: `+ P) [. G
    print("状态码:",response.status_code)' u" b  g0 Q$ ?
    1
    ' Q3 N. ]1 @( A# Q; @3 I+ H4 i当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url# e$ s: P6 ]# Q; O
    e、得到网页源码* o# n% ~3 m: X2 Q% A0 o8 D

    ( o7 l" Q, h$ u; L+ wprint("内容:",response.text)
    3 B# F* @8 I8 s$ a* Z" C1* r" t. s3 D+ _" \2 x6 d* |
    response.content是response.text的二进制形式$ g' N+ A; k7 A) b. @0 E

    / A8 |: x; h* n# Z7 X4 n至此,一个简单的爬虫请求就算是完成了。
    5 l  M/ {( _$ ~% ~  v当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
    : P+ P. P" ]+ z. yf、解析网址$ O3 D( Y1 f3 k9 Z' @" G
    刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
    6 ?, E8 y  a: {( M& z! V4 L8 ABeautifulSoup:
    $ l0 M; h0 f. C* l. Y( X首先导入需要的库文件:
    1 j# u: D2 {% C# }- t' I+ M2 O7 L/ H5 z
    from bs4 import BeautifulSoup
    $ z) G  P2 K0 N1' W, G$ g  x4 e; \$ m; D, q
    然后对上面请求得到的response进行解析:- }0 y% i9 @7 ?4 S! a

    2 g: b' f4 D  d; _" b6 ^html = respone.content.decode('utf-8'); g& Y0 O, d+ z; G
    soup = BeautifulSoup(html, 'lxml')
    - n: g5 [0 R. b1
    " Z! x1 ~! ?' {, ^2
    8 u8 v* v" ^' d, J; B以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
    " y9 `. M3 d  t1 X; A# G8 i# 获取head标签
    1 c  P! ^. O: x; C; U# n- P$ mprint('head标签内容', soup.head)
    & X7 g0 |0 y1 _1 B  i! O# 获取title标签
    . @; m) w, f% _6 Dprint('head标签内容', soup.title)
    " ^) W, F* y% Z: ~+ V# n# 获取body里面的img内容3 ?: q( [) e2 l% g- c3 O6 X0 {
    # 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
    ) R! Q, ?0 q6 o# Bprint(soup.body.a.img)   
    # B" e2 d0 `8 H+ k# 获取所有的img标签  使用find_all()搜索整个soup对象" }. W: K) X3 @/ h! {
    print("获取所有的img标签", soup.find_all('img'))2 t4 q- J2 _$ {7 Q) v0 N1 @" Z% @
    # 获取标签中的属性src地址
    ' h5 |0 O6 {- C2 w* g. r1 X& |- Fprint("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值2 R, O' m$ u, `8 `! c- B+ X

    ' e$ M4 K' [6 _& V3 x; x# H7 s8 z# S3 @7 h0 y" f& R2 `% r
    # 获取soup的name5 |& o& V. |3 b+ K" N9 N$ F
    print("获取soup的name:",soup.name)% N5 O' p2 Y6 ^; ?! s9 b
    # 获取a标签名
    2 W0 Z, N! I0 x% T( W' F; C7 tprint("a标签名字:",soup.a.name)* c9 ?* X* Z, `; a' R3 D
    tag = soup.a" X% q; x# ^; c8 D
    print(tag)) }9 _. f& J5 _% s" a! F
    # 修改操作  a标签改为b标签; ~3 u/ V" s: S* o" E, n0 c. m
    tag.name = 'b'   # 赋值后<a> </a>变为<b> </b>4 t6 H! R6 a+ g/ R) C' j
    # 输出修改后的内容4 w) h; u* A5 s) Y6 G  X* ~
    print("输出修改后的内容:",tag)6 G# M/ f7 Y1 r
    # 获取全部的属性 attrs. \% I) x* K& R* ]$ ?
    print("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)0 @& g8 x2 p6 \& [

    + a$ @0 R1 P5 h% G# 获取属性的class的值   根据键取值0 c% Q+ ~3 M. o6 i  K. J
    print("获取属性的class的值:",tag["class"])
    & `: ~8 n6 t8 x
    4 u* R% h; \/ {( f8 O6 N0 P. N4 F
    $ W7 U* [. n/ x' @: X5 b5 ^
    ' q) L$ s, q. W( W' e7 `+ V2 @: r  j  b6 w) p% A4 |0 |5 r; w' m( l: `
    """针对获取的标签属性可以进行增删改查"""
    ( S6 R6 H" P+ ]9 L% n# 修改
    8 }3 e5 M( S/ t0 E% W# dtag["class"] = "Logo"8 N, B& Q  M8 {  B8 x5 ?" D
    print("tag对象的全部属性:",tag.attrs)4 t* \. P- x0 q7 A4 r
    # 输出属性0 e# u! b$ m+ s: L  ~& f! m
    print("获取属性的class的值:",tag["class"])
    9 O: Y' ~! ?  g5 C$ d# 新增  属性id  赋值logo
    - X: s+ p  ]& a+ ~3 v+ b8 p0 v6 Q1 @tag['id'] = 'logo'4 ]# N0 [, A" B4 v, ?1 O% J7 r5 U" |
    print("tag对象的全部属性:",tag.attrs)0 t8 a5 q1 x% e! g( @5 J
    # 删除属性3 p5 u  x9 [) t
    del tag['class']  V6 p# w; }1 D# N* }; v0 y
    print("tag对象的全部属性:",tag.attrs)
    " B- w  [, h* v/ y* s  i
    ( W' A7 m3 u5 U( A  p* S2 J0 _+ S6 ]: F. f& v" S
    - C: x  e* J2 ~) _& Z
    """针对内容操作  (只针对标签,对属性无效)"""% U7 F1 Y3 r9 r2 H7 T1 M; C
    # 获取title标签内容
    ' N, j8 ^; B$ q3 {  Dtag = soup.title
    1 b6 \) s: f* R$ |& y* X- K( {# 获取title字符串
    1 j- e, }) W- g0 X, i* N$ sprint("tag对象所包含的字符串:", tag.string)1 x# I& E+ O+ ?' q9 G
    print("类型:", type(tag.string))- W- Z& M7 s. U. K+ c
    # 替换内容- Z0 y  U) i6 s( V" W, d
    tag.string.replace_with("你好")
      v0 p7 ?9 D+ G5 p+ [9 u3 Pprint(tag.string)
    - e& m) V. {% E. w2 |" c# <!-- 学科建设 -->
    2 ]( P- W# V' y: ], p# 获取注释文本内容
    : P; v. H% i* {0 Xmarkup = '<b><!-- 学科建设 --></c>'
    - t" V" L: z+ M4 O* Msoup_comment = BeautifulSoup(markup, 'lxml')$ R* u8 ^7 k8 T
    comment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索/ c2 n) i# k0 `9 H( O0 Y/ n
    print("获取注释文本内容:", comment)
    ) e, w7 F4 Y. o8 @2 N: N3 ^0 }# get_text()
    - p0 K" l6 q6 vprint("title的全部节点:",soup.find_all("title"))/ K- E7 f/ e5 `% F7 e1 ]. \7 R
    print("title的内容:",soup.title.get_text())' s' H% X$ |7 O, p' F: f. p
    """查找ul元素标签"""; r2 S7 x$ w/ q
    # class是关键名,匹配时后面必须加下划线_
    + ]; W5 |9 q; _5 E+ T# tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配
    " }% D' w6 P" U7 E: P1 K% j# print(tag)
    - w0 i* x* B  j. A$ H( s0 X& utag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配
    4 l+ n3 N, ?% a- xprint(tag)" s8 k* A0 [/ T4 ?
    # 查找名称为a元素的标签内容: W$ `  p7 c7 m8 M% E6 d/ b
    taga = soup.find_all('a')0 o0 m' j# Y( v7 f. L
    for tag in taga:0 o( g- n6 z  C2 e
        print("查找名称为a元素的标签内容:", tag.string)* t% K/ l: p  r
    # get 获取属性信息  获取整个页面的img标签图片和src属性值& O. Q, }( j$ E) ~3 p
    tagings = soup.find_all('img')1 x/ k% x  l% z; {' ^# k/ m+ s2 Y
    print(tagings)3 B/ T& d. q7 Z" x6 y( l  A" u
    # 循环输出图片地址3 o% e) A* m, n5 B: a5 g; d, e
    for imgsrc in tagings:) J7 D  p3 ?) n
        print(url+imgsrc.get('src'))
    1 L* w: W* v2 q9 |3 O+ T) |+ e: W8 p) K1 w" ^% h1 U
    """"属性只能做为参数,所有的操作只能针对标签"""9 U' t# ]' J9 u8 _' l3 W, r2 O
    2 G4 g7 E; V2 W1 h3 v/ }4 y/ ^
    etree方法:- w, q8 n8 T# Z( n6 I0 @
    导入库文件:
    & J1 R- F& h9 B+ A% l) g$ O
    . p+ L$ s- n' u, s" f0 J8 T* I& kfrom lxml import etree$ D' q. V6 r# K( G
    1
    $ m6 u% g& C& f5 f解析得到的response对象;: O+ d' A! n; Y0 g! Q6 Y
      z5 p8 ]5 j1 F" D
    # 设置response的字符集8 X  d9 b0 u0 E4 ?& o8 o
    html = req.content.decode('utf-8')0 w- [7 m! y7 L) I7 W* M7 I: @
    # 解析对象
    ; t. {0 q: a( shtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
    4 d+ a3 g- h* e: s6 g
    2 Q: n4 ^- P' ^: `. S- v常用的方法:
    % P9 U6 k( A3 Z, f9 G9 [) v) F3 `: q8 \  o" ^9 |) I

    0 d( n; h0 C1 _: l7 B* B; j8 \# 定位head节点(元素)
      t" ?% A3 ^7 z  j5 B' t) Bresult1 = html.xpath('head')9 j  ]" F1 ?- ~. G1 @
    print(result1)
    ' J$ {$ y: _$ B3 A# 定位title节点
    $ `& b, Z% n/ O, c- {result2 = html.xpath('/html/head/title'), q" O, v' e0 J! F5 t  C- H
    print(result2)
    # V$ b! Y! |/ l4 p" {4 f# 搜索节点  title节点5 }3 s6 Q# }+ S
    result3 = html.xpath('//title')
    ; L: u" G8 B, c2 Y& bprint(result3)7 A8 G$ ^8 t  n2 J2 A* E% Q8 W0 O8 a$ V
    # 搜索title内容  text()得到文本信息
    8 |# @. q/ I6 b4 U0 I7 p' \$ vresult4 = html.xpath("//title/text()")# ~: A- d; C2 T+ S; D4 a3 `6 C# H
    print(result4)  M: I4 i3 p' K- r5 U$ X+ B) x/ N
    # 搜索div节点) w' s1 }/ Q- x# `: F
    result5 = html.xpath('//div')
    6 x! y/ v; F, Q4 L; f3 m% [print(result5)
    ' {) g. |. G  p+ h3 B$ e# 搜索div节点 并用class属性定位
    6 U" o) y5 J4 @. d4 C$ ^result6 = html.xpath('//div[@class="news"]')! \* H3 Q8 t9 n
    print(result6)
    ; O- n; y) ?/ e5 c7 V8 b/ x# 搜索div节点 id属性定位
    9 U2 X& a: y. K- D  e& Z; @result7 = html.xpath('//div[@id="news"]'), Y0 n- z3 w: i/ b; S2 ]
    print(result7)
    6 O9 W5 L$ E7 ?. T* v# s) r1 R# 获取列表span信息
    : q, W) ~% _' X: o4 w+ c# wtext = html.xpath('//div[@class="news"]/a/span/text()')$ _4 L2 d" i: K  F4 P
    print(text)2 W& N  d, l( s; }7 Q
    . T& W( }9 _5 d! h

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
    8 c# f4 d' C2 R9 q/ a" I1 r保存的方式有很多种:
    " K7 [% L6 ?$ `( J1、保存至文件( X0 I) p6 ^" V. h% k
    csv、json、text
    * i: r$ h8 E, u: c2、保存至数据库3 h' C. }; F5 Z) @
    MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍
    ) u$ c5 u: i; j, h% t  c
      S5 S6 @  q, Q+ H. d* k2 T. p; _9 l$ [% p! J) i) \
    ————————————————( ^, s4 O" w) s$ |% N# E% H+ [
    版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    ' h0 v2 O2 D2 E. `( E' G# J/ D, f原文链接:https://blog.csdn.net/royallucky/article/details/105930473' @1 d7 h% ]2 s: i9 A4 u1 w( r, e

    $ m9 W4 |- y# {# ~" O6 K7 d. b- X3 N1 ~
    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-14 23:32 , Processed in 0.428622 second(s), 56 queries .

    回顶部