QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3702|回复: 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
    % s+ f& d  f* F; [& W% G

    & S9 d9 H. H: [& k  f7 Y

    3 {$ T3 C# ~& l( N
    手把手带你5分钟搞定爬虫(聚焦爬虫)
    . z3 `; C) o- k7 f; F+ t5 \% `

    . t2 H! f# r+ o1 S3 c爬虫的原理
    6 P9 k4 K5 X, {5 b7 _
    / p+ ?, @- ]2 K, P; g对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫1 G) h. x# Q6 I$ U, q' t  R0 P
    把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味2 u) ?4 P) U0 J& Y7 s, i
    所以说爬虫分为三部曲:
    & {2 B; ^6 i3 E" s2 x1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)$ e+ k# j- X7 D2 e. b
    2、去找到你喜欢的食物的位置(得到目标地址)
    , {3 ^. x( m6 U* @3、把食物搬回家去(解析网址,获取数据,存储数据)
    ' e( M: b. L! E% g它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)7 s, F! v0 t- H0 b
    a、导入需要的库 requests
    # H1 N) F' e3 ?# O. r5 V6 y, W$ ]2 e; U( Z4 D% s" F6 o5 R5 [& a0 L
    import requests
    ( B& A" w/ @: W# {0 Y1; h2 |1 z# L, y' A! }+ Z% ^
    b、明确你要获取数据的网址(这里以百度网站为例)
    7 t" ]# {) Y, p+ D% r& Y& i& s
    ! @% ^$ m* N+ N, }url = 'http://www.baidu.com'9 a# u! ]) _' ?8 R2 Z" m" a
    1* V- Y. U' u# _; q9 {" D! g& L
    c、创建请求& G9 ^/ R; a8 e- M* R, M% Z

    9 A9 R+ y. q* B8 N  ?response =  requests.get(url)
    / k/ F; ^  d2 l5 L5 I9 [6 h1
    % W. W) _; L. b5 gd、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
    8 V+ Y7 k" {* l# N* b* S* K' A1 p) G! n
    print("状态码:",response.status_code)
    ' E* c4 A8 p! k% K4 R# c1
    2 |% Z0 W* y. Y, e当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url1 d+ X; u" L+ r; q7 Q, J
    e、得到网页源码7 W& l6 ?2 g# Z# B  n) T2 X5 x- W
    ) A; O- N+ B7 n2 Z% ~
    print("内容:",response.text)
    ; o/ q" }9 z  s# e7 w) }5 u" V7 `1& h9 x) J& e# y2 ?
    response.content是response.text的二进制形式
    ! o: m' K! v6 X% v# `" T
    ' T- o- T1 B. m3 m+ [4 C: Z至此,一个简单的爬虫请求就算是完成了。, b7 D  z$ b+ P: _1 V
    当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
    2 G9 Y/ F- z' Yf、解析网址
    , i$ I# z! _) d2 G" T* J刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
    3 u1 h; ^. |4 `; g/ J% L% T$ l! H! nBeautifulSoup:2 T: e$ c6 m/ j  V- M/ M; A$ P
    首先导入需要的库文件:
    - W+ `+ S/ O# b7 p' Q* b5 z$ `$ h6 O9 J. Z' l
    from bs4 import BeautifulSoup
    7 f/ s$ h: i) p: s. Q" p1 U; `4 X1
    8 [, |8 z: `3 q) O4 v" u然后对上面请求得到的response进行解析:
    0 P) O( V" w( A6 ]  P& l  L- T4 }$ M! f" e% L* Q* |+ K7 Q
    html = respone.content.decode('utf-8')6 O4 F* E: m- Q$ Y) o' b# @( b; ^
    soup = BeautifulSoup(html, 'lxml')
    ' H! q+ f8 P" L. j5 O% w1
    8 a2 b2 G9 L1 T; c) S2' G9 |( L; m: \, X3 u
    以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:; ~" y) C" x: I/ ]
    # 获取head标签6 G9 a# S, {! \' O: V! j/ s" |
    print('head标签内容', soup.head). p& ?2 L. O% H4 K5 Y' [+ O
    # 获取title标签
    * I4 }8 J( P5 Q- L+ mprint('head标签内容', soup.title)9 n' \6 ^* L) m
    # 获取body里面的img内容9 P% v0 N1 t4 W8 y% N2 @
    # 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
    7 e! O/ g6 ~: ^, Wprint(soup.body.a.img)   - c- Q8 O  W2 _5 k
    # 获取所有的img标签  使用find_all()搜索整个soup对象+ Z$ @  e( e) ]; l% v% e
    print("获取所有的img标签", soup.find_all('img'))
      j7 m% ^  l  ^# 获取标签中的属性src地址
    ) n( [5 w8 }1 T0 y, @" Mprint("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值. Q) L) C  Y$ h& V
    8 [# P" y3 J, P" {( ~
    * X5 ]' G+ {8 l, B6 L2 O% w4 f
    # 获取soup的name
    ( }% @$ I4 i7 K2 Wprint("获取soup的name:",soup.name)
    ) a* [" d! a& S$ C9 @# 获取a标签名- H$ x+ b* R6 h$ `3 T9 a2 R0 y
    print("a标签名字:",soup.a.name)3 q' d; K8 z% o( {: e
    tag = soup.a
    # L6 p4 F: p5 K3 b2 P6 `print(tag)
    % k3 n' D: [+ {# 修改操作  a标签改为b标签
    $ \4 s* `3 o: i( }5 Mtag.name = 'b'   # 赋值后<a> </a>变为<b> </b>6 s$ E$ m, Y5 T. I  U7 ?8 H) R3 D6 L# F
    # 输出修改后的内容! P. J0 ?  r2 f1 \+ i
    print("输出修改后的内容:",tag)
    0 {  [4 ?- J% {, v: D; p. @# 获取全部的属性 attrs
    * }* W0 {+ X* A8 w: Zprint("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)* `) r: f% r! h: U

    ' k* Q% P! U1 ], ~0 S5 Q$ D# 获取属性的class的值   根据键取值  [* t" p  T, Y6 i
    print("获取属性的class的值:",tag["class"])
    3 _; n0 {* ?* ~! \" e
    . l. X$ I  s% Q) o' b- Z9 }& v1 [% u$ _8 ~0 c# C0 c

    3 e* I0 h6 b3 Y, F4 u0 [
    + T/ W5 i; i6 h! U0 N2 u8 F& t, B"""针对获取的标签属性可以进行增删改查"""
    , U. F+ i8 }+ d- S* m$ \1 X# 修改" ]4 f. x5 k8 q5 s5 ~
    tag["class"] = "Logo"& g9 U) n) W. s1 h: X/ [
    print("tag对象的全部属性:",tag.attrs)4 ~, Z" v6 ]- z0 {( ^8 b" C
    # 输出属性
    9 B3 K8 M: t8 c. X& T. Yprint("获取属性的class的值:",tag["class"])
    0 _/ T! }, Y! V# r- s# 新增  属性id  赋值logo1 W4 f7 i6 [! ~% H
    tag['id'] = 'logo'
      |! b* X( U. E. \: {% v; m" Fprint("tag对象的全部属性:",tag.attrs). d7 b7 r0 e" S" l. b
    # 删除属性
    $ \& Z; ]' i6 }% [3 [  pdel tag['class']0 g( O8 {% k1 T% ?' ?
    print("tag对象的全部属性:",tag.attrs)
    5 J* V8 _; J* {  s4 |/ o$ ~# R4 P. F' a: v% f" G7 Q
    ! B) m+ m( m" m* `

    1 Q2 v* {5 @1 Q7 X: F* R4 g"""针对内容操作  (只针对标签,对属性无效)"""
    7 j/ h4 k/ w1 W4 h: W5 H3 }4 N# 获取title标签内容( E6 k* c& p6 ^. g
    tag = soup.title
    7 X2 I  O9 f9 X+ I# 获取title字符串/ ^8 U9 Y9 w% k4 K1 z
    print("tag对象所包含的字符串:", tag.string)# D& O/ M$ ^. ?
    print("类型:", type(tag.string))
    4 U7 n& c( K' ~+ G' \- u  j# 替换内容; _$ @+ q7 X8 ~+ h
    tag.string.replace_with("你好")
    & i  S# C: J" Pprint(tag.string). X& e$ x# X9 d! a( w
    # <!-- 学科建设 -->
    $ |9 h5 F. Y! N! z( v- Y1 t9 X# 获取注释文本内容# Z0 G7 u2 _. ?4 U& u
    markup = '<b><!-- 学科建设 --></c>'  f0 [  A% \7 ~' ^% ^/ N, Z8 B
    soup_comment = BeautifulSoup(markup, 'lxml')' z  B' ?, u; {+ A2 s
    comment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索" t$ ], B' R8 }; [9 l
    print("获取注释文本内容:", comment)
    / Q( |$ W* r& k* P) `# get_text()& V% Q' q8 K0 O* K
    print("title的全部节点:",soup.find_all("title"))
    ) s- u) z- D; R/ t7 w! g$ nprint("title的内容:",soup.title.get_text())
    / F& {: f7 D# t# U"""查找ul元素标签"""
    * c# i( r" }+ \3 E+ G* e6 h# class是关键名,匹配时后面必须加下划线_
    1 I# ?% m. a5 p, b  r# tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配2 t7 R8 T( H! e$ \- a
    # print(tag)
    ' |. p5 }  Y; ~% ?9 qtag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配0 k& }# ?8 q; T0 ^! C
    print(tag)- @( b2 l8 D& d4 x3 {
    # 查找名称为a元素的标签内容
    3 S! k% K+ q7 @  d" ?3 gtaga = soup.find_all('a')) @; N! ]4 Y# }( L# ?& a
    for tag in taga:+ x7 a) `# U+ Y/ A& I8 i  [0 r
        print("查找名称为a元素的标签内容:", tag.string)
    6 R, p$ L$ J# a9 w# get 获取属性信息  获取整个页面的img标签图片和src属性值
    % o- A, n2 h" j& w( Y& Ztagings = soup.find_all('img')# g: c7 o& e- y* _  u! {
    print(tagings)0 I& l+ V' E  \: N( d
    # 循环输出图片地址( F9 h4 m+ H5 \& u
    for imgsrc in tagings:* [4 b3 `% h3 I. d
        print(url+imgsrc.get('src'))5 H/ m9 H* Z* o1 V9 X3 Q& @
    0 B; G/ F% J" r4 l, Z
    """"属性只能做为参数,所有的操作只能针对标签"""
    : X+ O' Q  w1 _' F! W0 n7 D
    * K8 f) H) ^( W6 P# cetree方法:
    5 Q2 h0 N% S+ i" Y7 o导入库文件:: T5 b0 t6 m9 R5 v
    . ?$ Z! v% t* @2 |" ^$ l
    from lxml import etree
    , B$ W, u9 s! R2 B* N" V" p1' k1 u, K+ W2 w4 N' o7 u
    解析得到的response对象;
    8 m8 l& p5 \4 L  Y9 H" `# {4 v3 f+ b: T- A- T! C1 r3 G; K
    # 设置response的字符集
    " ~9 ^6 w5 c0 s4 W5 b6 ohtml = req.content.decode('utf-8')9 Q! ?! r5 ?0 x
    # 解析对象4 v0 B% n" U2 l0 x
    html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
    ( E9 i* p  _- a; b/ j7 u& B6 l
    % \5 h+ v$ Y: `" A5 f' E常用的方法:- w0 P$ f; J6 k2 A+ I
    * r& m- @+ n) f

    - r8 O( b- T- ^# 定位head节点(元素)
    3 m. V! F& o. ?. r% d) Kresult1 = html.xpath('head')- q0 _" o/ Z* _; e* ^5 G
    print(result1)" h, ^- d8 J; u
    # 定位title节点
    ; K8 ~/ B: z, h2 e3 Nresult2 = html.xpath('/html/head/title')
    7 j7 M9 J4 e: S# T  V& D' M6 sprint(result2)8 y" S1 ~; b* E% ^! n* E3 i9 |
    # 搜索节点  title节点
    5 _: @6 q" [- r, L% h9 iresult3 = html.xpath('//title')
    3 _9 B$ k+ k$ fprint(result3)
    ( P* }& ?4 W1 A# 搜索title内容  text()得到文本信息) k0 S3 s' u% S' P" E
    result4 = html.xpath("//title/text()"). w7 A# h+ M' K% N) {  X& B$ r; Z
    print(result4)
    4 W6 L5 F; f' _6 ]  _# 搜索div节点
    ( ]& w2 J- F3 t( H9 hresult5 = html.xpath('//div')5 m' l7 m0 C1 |4 \
    print(result5)
    ) X4 N, `9 S7 w9 n$ Z6 k# 搜索div节点 并用class属性定位5 ^) F! @3 i7 K% K8 R
    result6 = html.xpath('//div[@class="news"]'); C/ e+ I( p; c4 L
    print(result6)2 [3 ?. R: \( p) p% [
    # 搜索div节点 id属性定位) Z* O% V4 u# H- _
    result7 = html.xpath('//div[@id="news"]')
    & w2 A# N: j  |; B# jprint(result7)' a/ i5 g( E8 n/ l- H
    # 获取列表span信息
    5 E7 n* h: G2 ?$ V4 [8 `; r% y- Htext = html.xpath('//div[@class="news"]/a/span/text()')
    $ J! q. f& j9 `$ {$ s- B2 uprint(text)
    % z1 n! r$ q1 |  n( x- D2 P
    1 o7 x1 |% Z& J; c% n8 s- |! }

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存7 E: ^9 _  h7 s1 x# y" c
    保存的方式有很多种:/ y1 \6 Z( x& R6 K7 T9 |. c7 E# o
    1、保存至文件
    : e# X' D) k* e+ Hcsv、json、text
    4 f, _1 D3 H( p! O: H  D5 Y2、保存至数据库
    6 N5 w- u" F7 Q" }% W# xMySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍
    5 Y, P) P' m, X) q+ D& j. X9 ^* N) Y6 M) {) C2 ?
    6 n% U! w. `; w# d
    ————————————————
    4 f: H8 ?6 S* _% h' w7 V版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。: d2 z- K/ c: g: V% k6 q
    原文链接:https://blog.csdn.net/royallucky/article/details/1059304732 U+ K5 `' D) ~( n+ \+ l

    ) R6 N5 d6 s. Y* ~  k" P: H, a* D, G
    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-6-15 15:30 , Processed in 0.400759 second(s), 56 queries .

    回顶部