QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3735|回复: 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% b: j3 A4 y! d4 V2 }

    ' Z2 u, B4 B/ J' d+ E5 c" `

    6 f/ i* R& e: v; g
    手把手带你5分钟搞定爬虫(聚焦爬虫)
    7 s+ F. f% `8 o5 ]7 {. A4 n

    * S% m9 J8 k' ^9 F& Y, a5 s' \) z爬虫的原理' J2 D4 o1 D3 ?6 d! p: ]  W' Q

    - @, {4 y5 N8 S% j对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
    + \$ d8 u1 D! y9 `& W把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味
    - U8 Y, p7 p% h所以说爬虫分为三部曲:/ N% v9 M( @; d* x1 U
    1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)+ A% J" m& F* I; |5 P
    2、去找到你喜欢的食物的位置(得到目标地址)) J$ t. E5 m& w/ ~8 J, K# k& n4 s9 r
    3、把食物搬回家去(解析网址,获取数据,存储数据)* `4 |9 L# }+ ~4 S9 ]" r
    它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
    ! `: k. \! x+ ^, g, d8 ]a、导入需要的库 requests
    ( {7 R. f3 N0 s
    9 ?% }; o, @- F. fimport requests- v1 X3 v, r1 T, j! p% ?4 F# a
    1
    / ?3 \9 f$ C2 |4 e$ {8 ~8 J/ Ab、明确你要获取数据的网址(这里以百度网站为例)% a+ s# |7 Y# U3 f7 e& s
    4 B; \& L/ t/ G4 P1 Z& D5 B0 c; O; n
    url = 'http://www.baidu.com'6 i5 P3 P& q% y" g0 |
    1, Z; R( V* B' j: F' i; P. G( `
    c、创建请求. _' M  w1 ~' n/ |

    6 t' @" y: b; i8 K1 O& A4 U1 [- d4 M7 xresponse =  requests.get(url)
    9 R; v  Q% U, `$ G9 ~1
    ' @/ \; `, k# u* Td、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
    . h4 D+ G9 |4 k) T+ @( J1 f
    7 B2 K. v/ s+ o' O$ ^( h& tprint("状态码:",response.status_code)
    4 ~4 ~* M( i* P1
    5 T1 ]+ _# `3 u4 G: r6 R% C+ k2 s当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
    4 L, \7 A% K9 Y  o7 }# H& z, le、得到网页源码
    8 h! H" D, }; C8 k: o5 u, n# G, Z" m! W  t0 {. G
    print("内容:",response.text)
    7 p- d! k9 E" Y9 O( X1  T, ?. Z& S- [- u: F
    response.content是response.text的二进制形式
    * p5 @7 o$ S0 W: ^) r6 T8 F
    ; @# q" h5 |+ O. Z. |! M5 v至此,一个简单的爬虫请求就算是完成了。  O# T( d' ]5 T6 M0 E1 X8 L
    当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据- ^' F* {2 b% \& i, A
    f、解析网址
    3 T6 A) Q9 a' m' ]刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
    . Q3 {, d: @9 }& u/ @0 o! K2 ?BeautifulSoup:3 q/ ^5 ]7 S! ~. r( [7 q- X( b
    首先导入需要的库文件:% Y5 W( X4 X* |; g/ F. i

    9 w/ D' @3 p: C# j" U. }from bs4 import BeautifulSoup
    ; s& Y# [' ]1 [: @5 ^9 m3 ^; K: u1
    + `4 j* b" E- y5 D! C) G2 u然后对上面请求得到的response进行解析:
    : R- R% e+ a0 P$ o3 F" H& ~
    - d' N9 T$ _( _* j3 @. f# zhtml = respone.content.decode('utf-8')* k+ z+ V5 q# S* i/ h
    soup = BeautifulSoup(html, 'lxml')1 Y& }$ x" r+ ?! `: k# r
    1$ m8 E9 T  L+ }0 l- v) e* U0 `. e
    2
      ~6 n& l( i" ]5 {! l- }+ G# s$ u以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:& Z( q* w, I* {
    # 获取head标签
    ; H$ R( w! h0 q* w- }( Mprint('head标签内容', soup.head)
    $ [' ?5 g( j: N* g- k# 获取title标签
    9 D& Z3 z6 j3 Q: Z8 uprint('head标签内容', soup.title)' w2 ?0 n( {+ q, g8 f9 R* s
    # 获取body里面的img内容; o$ r" P3 @" ~* r
    # 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)5 e" d) a* y7 y& [0 E" k- S
    print(soup.body.a.img)   
    9 _% k) @* B$ ~# M# 获取所有的img标签  使用find_all()搜索整个soup对象
    , }' |% J. }4 X- Y7 I6 Q+ N2 I* x' Yprint("获取所有的img标签", soup.find_all('img'))
    & X* Z: @( Q- F0 }$ Q$ {# 获取标签中的属性src地址! r3 Y, Z4 R  B/ ^8 y
    print("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值
    ; b/ [2 X/ r3 f, `6 T& C  B) {& Q* ]

    ! T& ?" U' a& G$ P# 获取soup的name5 k& p$ t+ h- F+ w$ F+ o
    print("获取soup的name:",soup.name)5 Q" V6 D* W9 Z- m) c
    # 获取a标签名5 H  |7 U1 B7 k# o
    print("a标签名字:",soup.a.name)
    / z9 v, B& f  F: q7 {2 p: w8 ytag = soup.a4 l; Y# w# l6 F: v. G
    print(tag)9 L$ s. w0 ~/ b4 B4 K3 a
    # 修改操作  a标签改为b标签
    0 v* i# d3 S# x7 ~+ ^tag.name = 'b'   # 赋值后<a> </a>变为<b> </b>$ ?7 I% ?4 f$ ~$ D3 S
    # 输出修改后的内容# K; O& ~  `" h7 ~. X0 E
    print("输出修改后的内容:",tag)
    , ~* ]9 Z! T6 y& x& C! u2 w# 获取全部的属性 attrs
    1 B; U) w, l8 ]0 y' t: a' ^/ Eprint("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)
    3 K/ M) m% R7 x0 L/ P5 Q# h# n/ u% O/ v2 G8 |& b5 a* i, d' N- w
    # 获取属性的class的值   根据键取值
    " u) l  @6 [1 ?9 Z& K. G9 s0 zprint("获取属性的class的值:",tag["class"])
    $ n8 n3 r3 U4 R4 W* r
    ( e# ]3 s  l* {, u, D" \  s0 p+ H9 ^5 P/ A, Q, O" F3 L

    * G  u& _$ Q; j7 q/ S0 v* Q* T' N5 c8 Q; u' A, f$ L3 r: g9 F8 n
    """针对获取的标签属性可以进行增删改查"""3 q" K9 E$ v$ B3 q0 _# k/ U! a) X
    # 修改- H/ j$ c6 J9 b# q$ A
    tag["class"] = "Logo"
    & k- _9 N( [: o; h! ?1 lprint("tag对象的全部属性:",tag.attrs)5 p7 i& P4 K* S. _: T
    # 输出属性, D! v8 [( q/ n  ]: M/ t
    print("获取属性的class的值:",tag["class"])
      g6 v, \7 V# p6 D# 新增  属性id  赋值logo
    2 S$ Y2 P( n5 T4 t$ R- utag['id'] = 'logo'8 B' K3 N* Q- e1 F
    print("tag对象的全部属性:",tag.attrs)
    - _! h/ j3 @$ g( j/ [3 Z0 Z& d# 删除属性
    , u, C& c+ S# W5 ]2 n' [del tag['class']
    3 F0 U7 d/ [* E# Lprint("tag对象的全部属性:",tag.attrs)% k1 M4 a, ~2 M2 f8 t, m

    3 c0 e* n5 Y' a; A4 J
    ' ?% @: W, q, F0 [) g4 r" s. p* h
    ' e( x4 \( r) r8 u. T# t( _! m"""针对内容操作  (只针对标签,对属性无效)"""
    + O, |$ z8 p, Q4 T& m# 获取title标签内容
    2 D; D3 N; H+ j% mtag = soup.title
    ) u9 L! ~# \9 g: ]" s# Z# 获取title字符串
    : I: Q  k* L! q( [9 _* s% {print("tag对象所包含的字符串:", tag.string)( o/ |3 H# D1 f! T
    print("类型:", type(tag.string))9 u2 Z0 n6 a! {( E
    # 替换内容( X6 n+ [; b3 M) v/ n
    tag.string.replace_with("你好")  g" Z# z6 O/ d9 e: b  ^
    print(tag.string)5 {5 N8 g* j& r: k+ E
    # <!-- 学科建设 -->( Y! a) I6 [2 j# g( ]
    # 获取注释文本内容
    * }% I& D0 E6 Vmarkup = '<b><!-- 学科建设 --></c>'8 ]- x& l/ k, P8 o
    soup_comment = BeautifulSoup(markup, 'lxml')
    # [3 P6 g; C- ~! e% Y) jcomment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索
    1 G+ S' u1 \+ X! M% P/ L/ o" fprint("获取注释文本内容:", comment)
    + I( k. c" l3 J; Q- c1 d6 I# get_text()
    4 Y6 y3 l# i4 A+ W! ]. iprint("title的全部节点:",soup.find_all("title"))- s. u2 e/ ]5 v" a: d  V5 u: R
    print("title的内容:",soup.title.get_text())
    ' u1 \% [* H. W6 o- g"""查找ul元素标签"""
    3 c$ E( I6 S7 S7 G) O# class是关键名,匹配时后面必须加下划线_
    ) Z" R1 \' t$ z; A; v# tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配' ^7 r0 [  i6 X/ }% L" F
    # print(tag)) l2 {* @& ]$ {  G& s- W
    tag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配' {6 r$ d0 d5 W6 {% Y: l
    print(tag)# P& \. [* r1 k/ m
    # 查找名称为a元素的标签内容7 `5 H! |& q' l$ A
    taga = soup.find_all('a')' T, y- q1 O4 }1 q, q3 [
    for tag in taga:$ p) G9 i8 C- a$ K" e
        print("查找名称为a元素的标签内容:", tag.string)$ v* m1 B. {1 e4 C: @( n- F  |0 a
    # get 获取属性信息  获取整个页面的img标签图片和src属性值
    8 W$ k- |2 ~9 Z( D  ttagings = soup.find_all('img'): C! q" j9 M- ]& o* w( B1 i8 l
    print(tagings)' _  X& V4 h/ R7 a) s
    # 循环输出图片地址
    # r2 V6 n% P3 W7 d! x" m( [for imgsrc in tagings:( N+ n0 \9 Y: Q( E, C
        print(url+imgsrc.get('src'))" \! H+ D2 V) M' f; A
    $ `) s5 o6 D7 W3 p( u
    """"属性只能做为参数,所有的操作只能针对标签"""- o! x2 Z# M& o2 r& n, n

    8 G1 u( D) a$ R6 b+ i" a7 r7 yetree方法:
    , t% N7 L& L1 p( F2 i导入库文件:
    5 x) ]$ Y; j' g/ O9 _  L( W4 H; D5 m+ n
    from lxml import etree# W9 G' x: F; @: [. B  `* X1 j
    1
    , i' M) N% p! }  Q, v解析得到的response对象;
      |( \2 ]% s$ ~& H3 b" f: x( T& U% N5 b' ]" ^! x* t) w
    # 设置response的字符集0 |6 H$ w0 {3 M# q* C6 ?
    html = req.content.decode('utf-8')% I  e7 H  M" B0 [* R" _! H
    # 解析对象5 t5 ^# ~& h, H
    html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))7 t# z3 C: e5 @/ g
    2 G- s2 q3 _  Z. R8 X
    常用的方法:8 K& O2 t9 c* d9 _

    & x2 U  r- j# v: n
    1 d) [7 p0 X+ w2 e& Z# 定位head节点(元素)! Y/ ?: U/ y6 g( Q1 |
    result1 = html.xpath('head')/ u# D6 w. O) e
    print(result1)
    3 m+ ]5 c( s3 S$ t+ `# X# 定位title节点# j5 o* n( [' \
    result2 = html.xpath('/html/head/title')8 c0 m+ d; v" @$ [" n$ P  |
    print(result2)
    2 ]% B6 m* l. C& s7 {. Y# 搜索节点  title节点
    1 ~0 p0 {/ G/ E. V  [result3 = html.xpath('//title')
    2 m' k3 g/ i0 ?print(result3)
    ! `+ r1 e8 E' `) Q6 A6 x# 搜索title内容  text()得到文本信息
    8 e7 s. ^: T. k0 U, i9 x4 \1 N4 v9 sresult4 = html.xpath("//title/text()")( O: S% f- V; x2 r8 K
    print(result4). s1 b1 e* h5 X2 @& x, |
    # 搜索div节点+ ~: h) F' B  l9 s1 G+ _1 D
    result5 = html.xpath('//div')
    $ Q. K1 {4 M7 y8 v' b) p' Gprint(result5)
    8 ?+ n; m* c5 s/ Q8 E- `# 搜索div节点 并用class属性定位
    0 {6 M: e: G2 g7 q1 V0 w1 Dresult6 = html.xpath('//div[@class="news"]')* z% n3 `( m5 v- r$ ^" I! k0 g
    print(result6)' v7 z. T: G& R
    # 搜索div节点 id属性定位
    " N3 U- N2 F3 l9 s, i$ ~result7 = html.xpath('//div[@id="news"]')
    9 e! T. z- L+ x7 K0 c& m, I- u" Lprint(result7)
      T% T& f" m; Y( Z% X! F# 获取列表span信息5 s* F; ]" p+ G5 C
    text = html.xpath('//div[@class="news"]/a/span/text()')2 C% b& E6 g. w: b2 X
    print(text)% e/ f/ }% j7 C& |' R- y( q
    7 z6 l) K2 M" V; x4 v) Z6 Z9 j' E

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存6 }$ u& K% K  \% c
    保存的方式有很多种:4 d# }8 U/ h) a& F7 \
    1、保存至文件
      a- W3 O. z! G: E7 W8 gcsv、json、text/ e0 v8 X! t% A* U8 V
    2、保存至数据库$ J4 Y& H% [8 W+ |' x& z/ q8 @% x
    MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍# M) E2 O) h& Y* d# t) Z/ [0 x8 D
    & }6 o3 R' C1 G6 T, b

    + a" `* [7 w( x: U& G0 m( C————————————————6 ]3 C; u6 d. _" N
    版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    2 S# R0 N* r' g+ l/ R5 d, ?原文链接:https://blog.csdn.net/royallucky/article/details/1059304732 i% {8 K; @. i

    - f" W7 C0 U0 o! @: D* Q7 o8 y7 G0 T/ r# `! f
    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-7-29 10:22 , Processed in 0.754820 second(s), 56 queries .

    回顶部