QQ登录

只需要一步,快速开始

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

    " p, U' Z1 X7 f) a: u% V
    8 u* @1 T; J8 b( T$ _: c# @
    4 P( M7 L% q7 c7 d- e9 A! u
    手把手带你5分钟搞定爬虫(聚焦爬虫)
    7 m1 J' R$ ^- z& e- X9 I! h

    " X; z; \& }+ i5 m2 _1 d爬虫的原理
    - D( a9 y$ `2 c) K7 i& N- P! r, h7 p; y/ y: W  j
    对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
    % g% N9 [1 {' ^把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味% v3 n$ N8 n3 b8 B
    所以说爬虫分为三部曲:6 i6 M, r: b  k7 J
    1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)" x+ `2 q, M3 {+ g; w* m
    2、去找到你喜欢的食物的位置(得到目标地址): z' Q2 y$ C2 B0 n% |
    3、把食物搬回家去(解析网址,获取数据,存储数据)
    2 [2 J" _& I1 h: m( L9 A+ \5 a它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)+ G4 H7 y% q3 J' @8 E9 z5 `
    a、导入需要的库 requests
    & g4 r5 h6 j5 S% R0 T; B$ Z$ q' G1 c2 ]
    import requests
    , V' V* ]( k) f7 ^  ]4 \18 ]: Z) C/ i& a( i0 @) P5 b
    b、明确你要获取数据的网址(这里以百度网站为例)& o. N- M" t( J% |8 x$ ?! d
    . O; ?1 t9 I( Y+ A! s7 N
    url = 'http://www.baidu.com'
    ( m4 ^. J5 b* {1
    - q1 m0 [1 E% N! ^: Z  lc、创建请求
    % \9 t9 Q! a5 H( l
    & _) {. u9 v3 f9 E# Rresponse =  requests.get(url)
    $ A8 k3 O! P, h0 z- Q13 m; m: b' P# h' L* }! ]
    d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)& b# c3 _: L8 ]# }/ J0 D  M
    1 j3 u& q7 L/ d) Z; e
    print("状态码:",response.status_code)
    , G  a5 v) ?% e$ H10 R. W3 X: [. p- C. J  k
    当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url8 ]' z" o7 W  ~6 {0 \3 `
    e、得到网页源码0 c8 O5 e4 H' G5 ~6 G; T
    ' C& [/ E, A/ D: M% s: H: f
    print("内容:",response.text)
    9 @7 |8 d( J/ s1! {% |2 ]/ ~! T& w8 k6 |
    response.content是response.text的二进制形式
    * V. K- y3 j5 d8 z0 k
    ! Z, d; W1 q2 u5 [至此,一个简单的爬虫请求就算是完成了。
    - J5 F$ y* s5 n" x2 }6 ]. R当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
    1 w7 X* m$ A5 Rf、解析网址
    9 q; K8 g# K; C' [' a3 _/ v/ m刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
      L- g1 F* }0 W$ V+ {2 }BeautifulSoup:
    ' M8 @; c/ q8 P首先导入需要的库文件:
    & u" P( V& z1 N3 j, E' m6 I9 d
    / w; Z2 d( |; z" }from bs4 import BeautifulSoup
    " w; ^% p6 P9 a( Y8 q1
    5 d, c1 K- l8 J9 L然后对上面请求得到的response进行解析:
    # P8 S# ~" A/ a- L& ~7 _
    , m  D9 N  W, n! k6 Ahtml = respone.content.decode('utf-8')
    ; ~9 o, P/ n1 C& R0 Isoup = BeautifulSoup(html, 'lxml')1 ]2 R1 u4 a9 D
    1
    & o( H: \4 `& h( }2
    ' o4 M! E$ A; g8 q以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
    6 h3 w: ]6 C: d% w9 p# 获取head标签
    . ~- l* X+ `( s% j6 Bprint('head标签内容', soup.head)
    ! E; q" o1 j$ ~- K" v' \4 m- Y# 获取title标签: u% `* H% u! P' F, V; |
    print('head标签内容', soup.title)
    : {9 T& o! _4 |5 `7 C# 获取body里面的img内容1 T* L- y2 p, x1 v
    # 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签). y2 W' ~$ B" T# B1 B* O' W
    print(soup.body.a.img)   
    $ x" b2 i7 R. g" z' L4 O# 获取所有的img标签  使用find_all()搜索整个soup对象
    % E5 l! ]# g) g, }6 W8 Sprint("获取所有的img标签", soup.find_all('img'))
    # u/ {1 W) m0 ^1 O# 获取标签中的属性src地址& O/ k9 o7 }! L( [) J# @5 [. I
    print("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值
    ' ?+ a6 t0 i# g: R" u; h
    , A) [% p3 K+ ?; [+ W
    $ Z, S: L4 _) ]& ?, \+ y# 获取soup的name
    , L; V7 a! Q' S: eprint("获取soup的name:",soup.name)
    * w2 M1 k+ y* d$ U% c# 获取a标签名- X0 G  B: ^2 s; l" T7 _
    print("a标签名字:",soup.a.name)
    7 J  \* D) Q1 ^% P, Z: t3 stag = soup.a
    . N6 p. |7 s9 A9 g3 `9 sprint(tag)
    3 P- k1 p. X/ V/ q$ _# ^# 修改操作  a标签改为b标签2 e  w0 b& \( }5 D
    tag.name = 'b'   # 赋值后<a> </a>变为<b> </b>
      ?4 r! W+ S, r. X8 H2 r! S' T# 输出修改后的内容: L/ x4 `5 p0 C* X6 R( b
    print("输出修改后的内容:",tag)6 @2 Y2 \1 r" D/ D
    # 获取全部的属性 attrs
    ( P3 A- b& e4 x! M+ lprint("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)
    " ?0 C0 L1 e( ?# e
    6 N( ]( U! Q/ G) R+ X2 O, t# 获取属性的class的值   根据键取值! h0 g* X& {( l1 W( u# @
    print("获取属性的class的值:",tag["class"])* S8 ~1 {( z9 l

    * c  Q5 u+ k- M  F) r) c) `, Y: c& a* @8 k

    " o! P3 _6 M) l
    0 p3 R- B' Y% a; R1 q; W"""针对获取的标签属性可以进行增删改查"""& U! j& i( z7 d# y" Q* P9 I7 H
    # 修改
    ! G8 h2 j' o0 l+ ?) gtag["class"] = "Logo"5 i0 c4 Y- f" d$ [, |
    print("tag对象的全部属性:",tag.attrs)1 d# Z6 N3 e" }! y' @/ `, h- l
    # 输出属性# w" r, t4 R( p2 w
    print("获取属性的class的值:",tag["class"])
    3 n. T5 ^. E6 b/ j  C# 新增  属性id  赋值logo& r+ p  [4 W# o1 X/ W* s  ^
    tag['id'] = 'logo'9 m. g; {) x8 Q9 O
    print("tag对象的全部属性:",tag.attrs)
      u3 A3 }, H7 {  M# 删除属性. U- V1 J$ i5 P
    del tag['class']: m$ O& l2 `  B0 X$ f
    print("tag对象的全部属性:",tag.attrs)
    * r; C% |* w+ v: l1 r* q" G
    / f' w+ O8 ?& q& W+ J
    3 g& T# W0 @: j+ T; z3 W; O7 r: G8 l& x
    """针对内容操作  (只针对标签,对属性无效)"""
    ( m+ I4 r6 h! e! C" K# 获取title标签内容
    & I! ^  \" E4 m/ C! U' P" rtag = soup.title  v6 j, m; a* r! ~8 s$ l- W
    # 获取title字符串
    # \' l3 N8 Y* \) D$ _: C/ [print("tag对象所包含的字符串:", tag.string)
    2 U9 ]& j1 [" Uprint("类型:", type(tag.string))3 ]3 x% W; x; |* @: c
    # 替换内容
    ( u/ M* m- ]. L3 {* \6 t% ]9 dtag.string.replace_with("你好")8 M' b% N' b' d, r7 R- Y8 d. ]
    print(tag.string)
    0 q- E. Z* Z1 f& ^, y" N# <!-- 学科建设 -->
    - b4 A5 w/ a/ P! Y2 [  S/ N. J3 n. @# 获取注释文本内容
    . ~9 Q3 f7 n1 `& I. {$ |1 mmarkup = '<b><!-- 学科建设 --></c>'" }7 {# W; \. A, [3 U8 W) F' N
    soup_comment = BeautifulSoup(markup, 'lxml')6 S. a4 Z) j/ \7 k( T
    comment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索/ m' P# B% Q; I- ]( w# E3 k# n
    print("获取注释文本内容:", comment)
    " M3 @6 W8 h' \  A* s% O# get_text()
    & e- c3 O. \3 Q# _print("title的全部节点:",soup.find_all("title"))2 [- D4 K7 w. p; [# ~6 _7 M- q
    print("title的内容:",soup.title.get_text())9 B8 _/ ~; D6 M
    """查找ul元素标签"""/ V. T; F5 Z5 f' L6 ?
    # class是关键名,匹配时后面必须加下划线_
    2 `+ H$ D( j+ K* k& ?& n# tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配
    . N5 i  f2 \" i, H9 e4 W% Z# print(tag)- l1 U  {: E0 `* a/ j
    tag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配) p7 a. R; a+ K+ t9 v% h
    print(tag)
    6 m$ r1 y* y5 B& T4 [# 查找名称为a元素的标签内容( i1 F# ?: O/ t; c7 x7 H7 h
    taga = soup.find_all('a')& Q) y4 i! ~% m' y' I8 t+ G; |
    for tag in taga:8 m# Q0 T( p- |7 {1 _: d
        print("查找名称为a元素的标签内容:", tag.string)9 @& ^8 l9 ^; @8 U/ K
    # get 获取属性信息  获取整个页面的img标签图片和src属性值  r0 _/ F: ~3 I
    tagings = soup.find_all('img')6 Q) p* @* j$ S% z7 q
    print(tagings); n) i& S* d" ~* ?: B! E, j
    # 循环输出图片地址0 R+ O0 S& I" t% [
    for imgsrc in tagings:- h& G3 s  N3 a8 O1 w; {6 \1 A: c! L
        print(url+imgsrc.get('src'))
    . C7 W3 P3 \6 _9 C& i
    2 m2 W3 b8 h$ x- Y. v""""属性只能做为参数,所有的操作只能针对标签"""
    9 @) y3 ]% O2 }" w( a7 T: e$ e2 @% b# i& H
    etree方法:' O2 G! f( P) n0 i. f$ X) E
    导入库文件:- v8 @. J/ ^8 M
    5 l' w: \/ @" [0 [
    from lxml import etree
    % j# S4 W5 [+ @& t. \$ J4 Q1
    # I8 Z7 _1 b0 P解析得到的response对象;7 p: f& o( x  C# q0 L" u

    4 V* Z8 u, F/ X8 C# 设置response的字符集4 L8 P8 Z5 s- C$ n# O  L
    html = req.content.decode('utf-8')
    4 D4 f3 M. _+ G# 解析对象* k9 o' G5 m( a2 p, K, x5 v3 S. ^
    html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))! M& `/ N: q4 A6 `. o# Z
    ' D, M9 k5 p& m8 }: s
    常用的方法:
    ; x% D4 Z  @4 D
    1 G8 }2 B5 {7 O( g) N; L" Z. S, U# t$ H: m0 |0 Q4 h: [; O
    # 定位head节点(元素), D9 W5 ?" r8 q( i* |' Q- p8 k
    result1 = html.xpath('head')( s) e7 m1 J) ?0 _
    print(result1)
    9 {! l, N, i7 |. I& d# 定位title节点
    ! l7 p8 i4 L( Eresult2 = html.xpath('/html/head/title')
    # W1 Z9 P: Z7 y2 x; bprint(result2)5 \$ t0 y+ }) j( z0 u
    # 搜索节点  title节点) J' g$ e; f9 |4 q+ A, v
    result3 = html.xpath('//title')7 m+ T4 v! ~# J* ^3 N+ |% }5 {
    print(result3)& S. L0 `, ?- @  J' I  f$ ?# F/ P0 p/ [
    # 搜索title内容  text()得到文本信息: ], c4 M5 C3 i4 F: y) g  L
    result4 = html.xpath("//title/text()"); @- h- [6 |  A/ B
    print(result4)
    ( g" I' m/ i! W7 G0 I" F. N# 搜索div节点" M: n2 b5 r3 W% n: d
    result5 = html.xpath('//div')
    ; y/ l9 R, i: g8 M+ T8 b6 l, fprint(result5)
    0 _. S- ]3 _% b( g# w  E# 搜索div节点 并用class属性定位* c" U" Q+ h* g& J" C& N
    result6 = html.xpath('//div[@class="news"]')
    8 B$ z' R: r$ P0 K4 Yprint(result6); u" {' ?7 U7 {# c( E0 ?- Q
    # 搜索div节点 id属性定位
    % S: }1 V; Z! c# I. L! C% v: `result7 = html.xpath('//div[@id="news"]')
    6 o7 r  O; f: _( `5 c: |print(result7)7 B$ q  `! y6 U" v% |+ y
    # 获取列表span信息$ `! M" P; n1 w+ G3 O" O) z
    text = html.xpath('//div[@class="news"]/a/span/text()')
    - V; Y. y9 U: zprint(text)
    ; o8 n, |/ ^9 u2 l
    , Y4 ?- _1 O* h. O- _. i

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
    , T3 ?# Z; e; M3 B& h保存的方式有很多种:+ `- C/ l- w2 n- ]9 q2 \0 h$ L
    1、保存至文件
    7 Z! }0 B+ _8 M, _6 Y% `2 H7 {csv、json、text
    3 c% v& v) [* x- \2 I# R5 @2、保存至数据库) t' E$ }4 m0 z
    MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍$ n: D, n2 d5 X9 j4 G
    1 k: [! F4 O& y% l( j3 t$ s6 e  E0 n5 Y
    4 z  s+ W6 Q# E+ q
    ————————————————- ?. h# z7 b7 Z( L4 K- U$ ~. c
    版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    7 N3 @0 b/ H$ f  Q! i( j, G$ M+ v原文链接:https://blog.csdn.net/royallucky/article/details/1059304733 [$ Y) @9 k$ w" g

    . K2 d  S- J) i
    0 Y( i. t, t: O; n' q( y4 v" x
    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-10-2 10:34 , Processed in 1.233046 second(s), 56 queries .

    回顶部