QQ登录

只需要一步,快速开始

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

    6 }3 d* K: I  W. ]2 B2 I( B
    ! A/ }/ c% z4 H9 T# k4 P

    . Y; M5 Y9 u- m& X" e
    手把手带你5分钟搞定爬虫(聚焦爬虫)
    : ^2 H9 C- X7 e, ?& s% W
    9 @! h# y1 d" y( s. b
    爬虫的原理
    ! U: w0 ?! H5 U* ?
    7 L: V$ I0 c% `# i4 O9 V$ e对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫# k, E) t2 e% J9 o: O9 ]/ m/ o
    把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味. N9 m" h9 _. _9 M9 r
    所以说爬虫分为三部曲:
    6 t2 ^7 g* {3 I( J! p1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)7 [* k; q8 |; _* w+ U
    2、去找到你喜欢的食物的位置(得到目标地址)
    3 V5 b, B9 O! P7 P3、把食物搬回家去(解析网址,获取数据,存储数据)4 b- p/ @) G1 l
    它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
    8 N8 H) e$ Y1 _6 ca、导入需要的库 requests! o& t, B$ n. f2 V" ]2 m) t
    9 q( m/ q  F: ]$ u, N
    import requests
    - _8 A2 t9 E8 ~; ~4 p5 z0 |1. S( [  f2 h4 C- q# |
    b、明确你要获取数据的网址(这里以百度网站为例)
    ! `/ W0 n9 V/ r* x8 y( H. l9 I, G. \3 F" x+ G) Z
    url = 'http://www.baidu.com'
    3 b, k2 q; E' ^% Q+ N1
    3 {6 T! k7 x5 V6 Y% fc、创建请求9 y2 T2 U# G  M: L

    ! C9 B" D. w9 T" T$ nresponse =  requests.get(url)3 y- J* D+ Y& Z5 m* m# D
    1
    # o8 O' E' d, e0 `* od、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)3 V7 k5 l* _. W& h7 N9 w$ ?4 r
    ( J/ H: n/ E9 ~, k- {) j5 e# k
    print("状态码:",response.status_code)! f$ M) S& b/ o  M; s* ?6 c
    1* O  U3 C! Z! t- Q$ g! @+ v
    当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
    3 j, W; \- c. b, x; n7 Me、得到网页源码8 ^% j) B6 M4 m) |& A* v
    * O% j! @& }1 g; N6 ^) I, r: d
    print("内容:",response.text)1 y( Z/ V% F. ^! w3 }7 P( z
    18 c/ u# `/ v' {2 o* |$ p
    response.content是response.text的二进制形式
    ; h% T1 V, P+ S" I  V4 k) d  }, g5 n. Q4 \4 a- h" {
    至此,一个简单的爬虫请求就算是完成了。; U( p( n2 R+ r6 h
    当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据$ |; W! @6 K$ ]1 d) b3 Z! b, Q
    f、解析网址
    " m6 i( p7 L* i4 s! f, u刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
    1 s0 c7 e, m2 E4 b' o1 YBeautifulSoup:
    ; z  G; x5 r. }2 H. c首先导入需要的库文件:6 d7 A7 Y! [/ }% t
    - u; R7 y4 r: s* \& [
    from bs4 import BeautifulSoup# w* J& @9 c/ B+ j9 A
    1
    7 F2 e# j- t" o) ?' Z3 {0 a然后对上面请求得到的response进行解析:! O# z7 [; r6 Z6 ~, _4 c1 v
    1 G9 I7 s! @/ y
    html = respone.content.decode('utf-8')+ p. u' Z' @5 f9 {9 R
    soup = BeautifulSoup(html, 'lxml')
    ; \* \6 e$ X" R9 [1
    , e- J0 N9 V8 @9 S3 J7 E2) a2 J- U! i- ?" E
    以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
    ! u( i' }8 S7 W, f# Q# 获取head标签
    % p* L4 _8 Y3 g8 S! V2 rprint('head标签内容', soup.head)
    . L2 r2 M+ @' B! d/ `- f* @# 获取title标签
    4 O* Z9 ^% {4 E; kprint('head标签内容', soup.title)8 @7 {9 {9 }) i3 b% A" p! V' x. A
    # 获取body里面的img内容
    8 \& j& V, h1 ?( }! V# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
    * ^: e9 Q6 Q! w! {0 Yprint(soup.body.a.img)   
    1 Y9 z) d* P: Y! e4 p6 U) d/ b6 Y# 获取所有的img标签  使用find_all()搜索整个soup对象
    ( p: l8 }- |/ B" \" h8 B# hprint("获取所有的img标签", soup.find_all('img'))* z: ?5 p4 F' p$ w
    # 获取标签中的属性src地址
    : A. m9 H* o' qprint("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值
    & Q  B" I; b8 d7 P- ], e" T1 K1 G  N) x
    9 g4 {$ Y# f" \# |; h$ e
    # 获取soup的name5 z; R' u; N: E
    print("获取soup的name:",soup.name)% y; d' H! G* |" g0 G7 i+ f3 }) Y
    # 获取a标签名# v& m+ t; {2 o3 @+ E, Y0 @
    print("a标签名字:",soup.a.name)
    : P  J9 M* t" k: I- Y& ~tag = soup.a
    6 h9 d" h4 }* G" I: w3 xprint(tag)0 Z' h- Z' J) t( P* t3 P
    # 修改操作  a标签改为b标签
    9 j0 ?* S0 Z0 m5 d# rtag.name = 'b'   # 赋值后<a> </a>变为<b> </b>
    % Q7 K0 {. J3 [; N4 E0 y# 输出修改后的内容
    & }3 U! V. d8 x  G" M$ wprint("输出修改后的内容:",tag)$ o& C( U9 `- Y; w( L
    # 获取全部的属性 attrs1 n. ]2 x, [; Z
    print("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)/ l8 I5 J3 T8 J
    6 j9 [* V8 Y# U+ S. J  U
    # 获取属性的class的值   根据键取值
    4 M& A) y8 F" M; m2 {( }* }print("获取属性的class的值:",tag["class"])
    0 I' m* C4 }' R' [! R. P6 s# C$ w# f- K
    % p' m* }, b# x9 Q0 y2 |8 q' w1 |$ e4 r# L7 r0 _& E6 n- X: J

    : i2 Y! R- w, n  P5 R: o5 y( G2 T6 y. z+ x- Z6 r9 R
    """针对获取的标签属性可以进行增删改查"""
    3 V. ^- j) W8 p; n* o# 修改
    : N& a' j! d) C7 N. Q' ktag["class"] = "Logo"
    * K5 [8 U. L  @2 F/ m& X$ Oprint("tag对象的全部属性:",tag.attrs)
    ( b1 z4 k" u2 }0 b" X/ h2 Y, f# 输出属性% n4 l7 J7 F9 F% B7 `1 z
    print("获取属性的class的值:",tag["class"])4 C+ B4 R  z2 S! a  M; k1 V8 N
    # 新增  属性id  赋值logo$ @; J& \5 W* S& _+ E) o7 V) n
    tag['id'] = 'logo'
    1 h3 R* A0 X# g" U1 u3 H$ K1 nprint("tag对象的全部属性:",tag.attrs)/ Z. V6 y) n, A1 D  N, k! E
    # 删除属性7 I. g% U3 ^& T
    del tag['class']
    " O; W- M' `+ ]/ r" Bprint("tag对象的全部属性:",tag.attrs)- a& i6 f7 P* D) B: i6 P3 c
    & _# ]6 M: @/ p1 Z4 C. e

    . F7 r+ d3 Q2 n" K
    ' z, ~, D1 b) e2 u% a: p- \3 s"""针对内容操作  (只针对标签,对属性无效)"""9 z$ i: I) ]' i! e# S
    # 获取title标签内容: s" a! i' w# K
    tag = soup.title0 t: D0 w7 B/ C
    # 获取title字符串! E  e. `0 r  k2 `5 N. c
    print("tag对象所包含的字符串:", tag.string)) Y( @2 q% @9 ~: [; b" {
    print("类型:", type(tag.string))1 S0 [; W/ d2 q; V. a- Z
    # 替换内容8 K" C% Q4 C/ A+ j; B$ Q0 t# g
    tag.string.replace_with("你好"). M, {. M: c5 |% y9 b! t/ ~
    print(tag.string)! N, e1 w2 |# }; V3 t  C! b! l2 g
    # <!-- 学科建设 -->
    . V; S0 F6 L! ~5 L* m# 获取注释文本内容/ J0 y  S0 d; \% i
    markup = '<b><!-- 学科建设 --></c>'
    2 d; O  s: I* N" Esoup_comment = BeautifulSoup(markup, 'lxml'). b6 {" A, r# `
    comment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索" P, X2 [/ D: S6 y  L9 y$ u5 n
    print("获取注释文本内容:", comment)/ u9 |  T7 f( A" _& w! h
    # get_text()9 ]" T2 Y  A. D
    print("title的全部节点:",soup.find_all("title"))
    7 N! }  r2 n0 a6 Y8 t) \print("title的内容:",soup.title.get_text())4 n6 t6 T1 @' q
    """查找ul元素标签"""! ~! G+ X5 g$ r5 f- n3 q
    # class是关键名,匹配时后面必须加下划线_: z% [' _  ^% t; k6 ]. S, Y
    # tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配6 [4 O* h4 O. |, E1 P: o, \$ l
    # print(tag): g# y- t! i# W; e) d) b
    tag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配3 |6 T9 C1 d8 \6 g3 e
    print(tag)
    6 k4 O8 j& f. V( w9 _# 查找名称为a元素的标签内容# z  q) c2 h# u
    taga = soup.find_all('a')# R. B6 |8 F, r
    for tag in taga:. t. R4 \3 p1 s8 c% F
        print("查找名称为a元素的标签内容:", tag.string)3 e2 Q$ H! R. ~+ [
    # get 获取属性信息  获取整个页面的img标签图片和src属性值/ i5 r' O" V$ g0 r$ t" w
    tagings = soup.find_all('img')
    * ^# I( |1 V5 f" t% v6 r4 G, Q$ x" @print(tagings)
    ) ~. O) E4 O/ q# a( I# 循环输出图片地址- J/ |6 W# ]3 M3 b8 j
    for imgsrc in tagings:
    ' ^$ T# }* }" N; T9 S) N+ L    print(url+imgsrc.get('src'))
    9 I' H% ?3 d; y
    % s4 w/ b; w5 S8 p# W4 R""""属性只能做为参数,所有的操作只能针对标签"""0 i1 M* A1 N9 H
    ; t; ?" L, m2 U. y6 Q$ j
    etree方法:
    / S; V1 ?" Q$ d6 k3 G0 m导入库文件:
    0 L3 `. s* m; [# S/ G! `6 U$ A; {' Z/ O1 x' J4 C
    from lxml import etree
    ! l2 ^/ i# p4 W# t6 R* D1 e/ A1/ J0 L) {0 u7 a+ M) V- G" O! h
    解析得到的response对象;
    7 p3 _- ?( h9 X# c& Q
    " L9 o2 y3 m5 X# 设置response的字符集
    9 N3 Z7 w+ F; O! P. V2 R0 Xhtml = req.content.decode('utf-8')  h. y' M- I4 b& Y1 Y
    # 解析对象
    ) G. D. L% j! v% u5 P8 thtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
    * }6 V& J9 r8 {" q0 h- h: F
    * ^) d/ u7 _! e# G6 D& w, `$ D( s& s常用的方法:
    & [2 V: E6 v5 r- b3 u1 g" h: L1 }9 [2 h3 \

    3 I$ z. k, X0 W( P2 o# 定位head节点(元素)' V5 v8 y/ O% l8 r4 Y3 A# v& Q+ U' U
    result1 = html.xpath('head')
    ) z6 j. m" Y' b, Z7 Xprint(result1)6 s; h) P) b; m# X3 \3 L: ~
    # 定位title节点1 n* J/ E" R  S# X; H9 `1 a. P
    result2 = html.xpath('/html/head/title')
    & i  Z' W4 ]1 Y- a# L! Uprint(result2)
    3 K/ G, s% L( f% e+ Q# 搜索节点  title节点7 G8 L% `7 l" U* I; w
    result3 = html.xpath('//title')
    8 g+ p1 A; r. w. Y) C9 Q$ Dprint(result3). u9 i& |) Z9 H& q$ S' J4 x5 N
    # 搜索title内容  text()得到文本信息0 Y/ S" V' y' }  @, ^- r6 v. e
    result4 = html.xpath("//title/text()")
    2 B; X2 r8 ~3 T% zprint(result4)
    1 e& R% c/ e/ \' r4 T, u# 搜索div节点/ E9 b1 i+ I: O. v& R" F* Y. o
    result5 = html.xpath('//div')% d% b1 ^3 I7 P1 z
    print(result5)
    6 i5 E% J7 x$ i& S4 ^( R# 搜索div节点 并用class属性定位6 o4 d. y( i* g& _4 z
    result6 = html.xpath('//div[@class="news"]')
    8 W$ Z2 q" @+ A& X' E2 v4 Oprint(result6)* H: f* o! E: U) R% M5 F
    # 搜索div节点 id属性定位& L4 H( }4 ]  T. d
    result7 = html.xpath('//div[@id="news"]')/ y  J' o# y* {2 U* w2 w
    print(result7)5 z7 b& v3 L3 j& J, T6 D! S
    # 获取列表span信息
    9 k; ?) |0 [1 ~; I5 [/ b/ jtext = html.xpath('//div[@class="news"]/a/span/text()')5 O) m5 T+ B, S  G' i0 A! W
    print(text), Q0 F' c  q5 J: Y& ^( H1 |. \# k

    3 C6 y, h& a( a/ o

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存8 M; x) m5 j* w# J
    保存的方式有很多种:3 ]/ _+ l1 a% i) D. [  Z* ]3 {
    1、保存至文件
    * l- r  R' T* r5 E" F) ]' M$ v$ Tcsv、json、text5 R4 T9 V6 m. [! ^6 }. u
    2、保存至数据库
    3 i# P; S- B' r  l, Y6 HMySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍
    8 T( M# c& v* k# T- E( U0 R( L; A7 ~6 G: @) z

    2 W6 ?$ n3 b5 S7 m. K8 y————————————————& P) A4 T" T1 Z) t
    版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。) u# H+ d) T/ [* A
    原文链接:https://blog.csdn.net/royallucky/article/details/105930473
    . |/ ~; ~. X& |$ d. I% u' D& B
    $ ^, l/ a+ x' m8 G; x( m
    + w0 g, P* C8 g8 `) _% m! e
    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 06:04 , Processed in 0.436237 second(s), 56 queries .

    回顶部