QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3340|回复: 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! M3 L" A! Z" A
    : w/ |7 {6 d! M* |$ |- ?2 p
    . c9 k$ v' S: o  t" \
    手把手带你5分钟搞定爬虫(聚焦爬虫)

    & k+ `; s0 d8 A5 ^$ P. h
    + i) D: t+ H. l2 j- `爬虫的原理; i, h" a7 j/ Y8 P9 J. k7 a' f

    7 b3 ^- I1 h- g+ T对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
    3 A8 @2 H, f6 v! U0 o( t9 u把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味& S6 ?. S( ^+ \; V3 f: ]4 i
    所以说爬虫分为三部曲:+ W( p7 ^& r6 w! Z- \, \) l% d
    1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)/ O; G' Y1 [9 l* k
    2、去找到你喜欢的食物的位置(得到目标地址)
    0 ?* }! I) n7 \1 _; G; Y6 \3 }3、把食物搬回家去(解析网址,获取数据,存储数据)
    4 E  e8 a4 \2 ]' E! E它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)# W! P" s1 C! t5 H+ _
    a、导入需要的库 requests
    2 @, n0 R- n! j+ z6 T1 D7 x) H* X4 K1 G" K0 b
    import requests# K3 C2 s6 v  i
    1% S' j# ?) p' k" B
    b、明确你要获取数据的网址(这里以百度网站为例)
    6 i% G: ]( _( ]9 \
    , X( x1 J8 Z7 N% R& V! N  Burl = 'http://www.baidu.com'! M. j, V1 {; ~; r  }: s
    1
    5 t$ v1 H$ z: Tc、创建请求
    4 I% o# `6 q3 n5 F/ |3 @2 _- l; s1 s- e. }; C  l2 W- a
    response =  requests.get(url)! H3 w: K. F  p$ c1 z
    1
    8 k; J4 P! u2 M( `d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)- t( Y+ s' I7 v2 ?+ {9 L+ ^) J7 Z

    % V% ?' o- @, v0 Q: J; Kprint("状态码:",response.status_code)
    7 {2 g+ g4 m2 o2 o# D8 [19 q8 X$ D- |1 V& O
    当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url
    ) o2 \- v$ @% ]/ B  ae、得到网页源码/ D/ c" c( c8 p0 }# c& m; f) C' _$ i
    7 V7 I; u6 N0 J" n# B* ?' K& K+ ?
    print("内容:",response.text)
    $ ~( u' Q% l2 j9 z1" Q' U, P3 l4 ]% n! \
    response.content是response.text的二进制形式
    0 k2 ?* B8 Z( c6 d% e; L9 ^7 z" E/ P
    至此,一个简单的爬虫请求就算是完成了。; w& j: u5 W  e+ z& ?5 M- _3 t
    当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
    ( N* S; Z- v: I7 F5 N! [. h1 l5 N  nf、解析网址; e; I. E+ k: `# n% f  `6 L0 C
    刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
    9 n0 r+ k: }) ?; xBeautifulSoup:8 o8 u- S/ R+ R' F8 s: K8 Q% O# q' }
    首先导入需要的库文件:
    8 `6 L0 r1 d0 c9 f5 O! C& N& F; r+ J! I! K# a: X% |
    from bs4 import BeautifulSoup# I; I" E) B* q" j' R  R) r
    1
      O/ W; z) b) e5 O8 Z1 A( V然后对上面请求得到的response进行解析:
    + S) I  D: Y# Z
    ; I7 {0 ^3 c$ O3 @1 w/ |, _( zhtml = respone.content.decode('utf-8')' F0 K: }& m9 C7 t
    soup = BeautifulSoup(html, 'lxml')
    ) \$ @! G7 [( q  ], L2 {1. c5 H  d! ?# N& @0 _
    25 Q/ h' {0 m6 B4 O+ {( c6 t+ `
    以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:, r; _  t) w) B) m* f, U8 e5 g
    # 获取head标签- j2 i  a% j) \8 f% P- ]5 m
    print('head标签内容', soup.head)
    2 X& F$ b6 [4 a% n6 Q! H, B  j# 获取title标签
    & o* V, p1 M2 Y& wprint('head标签内容', soup.title). J& [( c6 k: x5 ^" F1 \- M+ B
    # 获取body里面的img内容$ F1 h$ I) [* u4 l5 q- `
    # 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
    2 O) f5 f7 S0 k5 r. B. ?print(soup.body.a.img)   ( ?1 K* \, C! C& ^$ G
    # 获取所有的img标签  使用find_all()搜索整个soup对象
    : ]6 C1 h  \& }- w/ u, w6 Qprint("获取所有的img标签", soup.find_all('img'))
    2 S( x, a1 x3 ~# k* @" {' z7 k3 Y- T# 获取标签中的属性src地址: _# v2 z5 g* s  a
    print("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值; J0 d( h. V5 }1 F* e

    5 `6 g& R- ~! [9 Q5 k/ C8 }, K8 j* ?) o, I% u9 M, [& E1 G8 T% f
    # 获取soup的name
    $ Y3 f8 @5 ~0 u$ y% H9 kprint("获取soup的name:",soup.name)
    ' \, `- ?* {" V+ ^# 获取a标签名
    : \4 b1 `5 a6 a1 s8 @$ gprint("a标签名字:",soup.a.name)9 S5 u3 }; Y) j
    tag = soup.a! ^; [- e8 h% N. T: F/ T
    print(tag)
    # W  G1 L  j2 _9 l* c6 G% F# 修改操作  a标签改为b标签; r6 F# }3 |! U/ f
    tag.name = 'b'   # 赋值后<a> </a>变为<b> </b>& U8 S) ^, D* T1 y/ A
    # 输出修改后的内容
    : d4 v8 P3 X) v* E1 ~print("输出修改后的内容:",tag)
      b" D, A0 X# W- O3 U6 v% v$ S  u# 获取全部的属性 attrs9 y% D( A8 h: n/ g+ z
    print("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)
    * H7 g( ^6 k, N. N. E/ j% Q7 q, }2 C5 g+ A) A% F4 b5 |
    # 获取属性的class的值   根据键取值- h  ]1 f$ |) K0 A- N" D/ u2 r3 e
    print("获取属性的class的值:",tag["class"])+ L7 y5 [' E+ |5 L/ }( z
    : u% h" M- ^1 J6 K# r" V
    - [  V+ G# m) o$ P1 z
    - u9 x3 u, A3 l

    & t7 ^2 ~, W' j0 L3 a; C1 V"""针对获取的标签属性可以进行增删改查""". [3 T$ C9 \/ @1 `1 e& _2 o$ d- ^4 N& K
    # 修改
    2 J7 u- g5 b4 O8 [9 f3 a7 ^tag["class"] = "Logo"7 e7 K) }# Z$ D# u, N: n
    print("tag对象的全部属性:",tag.attrs)9 W0 ~. M( f& n; O9 D
    # 输出属性
    0 M2 d8 J) @# u% S4 C" gprint("获取属性的class的值:",tag["class"])  s) }/ q, X$ }& {
    # 新增  属性id  赋值logo3 p5 N, o( f  ?
    tag['id'] = 'logo'
    1 E. n" W2 ^+ |$ p, X* h$ gprint("tag对象的全部属性:",tag.attrs)
    , x* |% f' f* N# k$ R3 R6 x# 删除属性
      a( b  j, d- _; @! l' W/ Hdel tag['class']9 y6 h# O+ T. c9 ^. g
    print("tag对象的全部属性:",tag.attrs)' D+ A- L. j/ `; J7 i( Q4 S$ f, m
    ' Q" ?% w" [# {, s0 `: J
    , c/ _8 P  ~# b! c' i  s: C. z
    5 p& _9 {, h; Y% p2 P" E, z+ U
    """针对内容操作  (只针对标签,对属性无效)"""
    ; ^. c( `5 X. @, P& d& b# 获取title标签内容; C# F8 E! Z8 u7 l7 d& y. b
    tag = soup.title
    1 K( F6 r  F+ }# 获取title字符串7 ~$ ^( ^: ~, f8 X: \
    print("tag对象所包含的字符串:", tag.string)
    + N. L8 j6 J  [8 nprint("类型:", type(tag.string))
    $ K1 H: u" z# ~" j; [6 a1 V* a# 替换内容
    & ]4 W# m$ L8 P& ]  |) C4 ctag.string.replace_with("你好")$ R2 }: A: `$ g& g6 I
    print(tag.string): }: k0 {7 ~, w0 }; ^7 x/ G( g. k
    # <!-- 学科建设 -->
    $ {) p9 Y0 V3 F/ F# 获取注释文本内容# T) q% p0 S$ o
    markup = '<b><!-- 学科建设 --></c>'
    1 Y7 g4 N$ ?9 C3 E$ T$ j: p* rsoup_comment = BeautifulSoup(markup, 'lxml')# k/ i( T* P( _/ [
    comment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索
    1 C1 d0 j& o  Oprint("获取注释文本内容:", comment)3 X$ f6 w6 q0 J/ v
    # get_text()
    # r2 Q6 P% G  L" a/ U$ J- pprint("title的全部节点:",soup.find_all("title"))
    2 l- K9 D* Q2 D* [print("title的内容:",soup.title.get_text())
    3 N7 ^. T9 ?& D"""查找ul元素标签"""
    & m2 ]+ ?! C; R  ^5 v1 x# class是关键名,匹配时后面必须加下划线_
    9 _5 k% ~' `8 u" A$ g. D# tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配! ?+ K* C* L$ E( u) \& y3 E1 A1 K
    # print(tag)
    9 F1 s5 }* {, ^: ttag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配
    / j0 r# V) A, T+ i7 F2 l1 Pprint(tag)
    - h7 I& ]1 U3 u  D2 T# 查找名称为a元素的标签内容
    " U: @& E/ \4 l7 ~0 O, T# g+ ^/ Ztaga = soup.find_all('a')% H1 Y9 v1 k  ?2 m7 m3 j# K& F
    for tag in taga:- q4 M: T! O- f8 u/ z2 O/ K8 J
        print("查找名称为a元素的标签内容:", tag.string)# m7 R& _: ~- }( K
    # get 获取属性信息  获取整个页面的img标签图片和src属性值
    - X" c+ K; l( btagings = soup.find_all('img')
    $ I5 F4 {" c6 r( R) z8 pprint(tagings)
    % M" `  O! E' t7 R; R0 n# 循环输出图片地址; g( J1 N1 B+ J4 I
    for imgsrc in tagings:
      k  u! r- m$ j% T. I& \    print(url+imgsrc.get('src'))! a6 S1 J" e9 r# S4 H8 f5 B& M
    , o) m! ^( F+ P  e. {3 j
    """"属性只能做为参数,所有的操作只能针对标签"""
    , t0 s2 @+ s9 k2 s  e8 P+ C, Y  v% }
    etree方法:
    8 M6 T; @3 x: L5 k4 p导入库文件:
    8 P/ Y$ ^$ B! S" s5 A- Y9 P
    6 C; y2 u0 K5 C6 q9 B: \# Ifrom lxml import etree
    % v) \. H& x, [8 |  O1( A+ w$ {  L7 d
    解析得到的response对象;! k% t2 `6 R, p& y# M( U
    " L8 ~9 k, E3 o1 y+ s8 A
    # 设置response的字符集
    & J. O- d7 R2 ]1 E! u  shtml = req.content.decode('utf-8')
    + S2 {" Q) a2 ^9 M" G9 P# 解析对象
    ! q0 U% C" X% b4 y' b* f2 u4 k- s1 Ahtml = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))0 [1 ^3 e( [; I' T, y( |

    6 g1 `, G* U  b7 w( W5 C0 e常用的方法:" a& H6 H" Q, Y6 O" B

      l. A+ c# [; O/ H1 O. y2 w$ m$ a1 e# I, L8 z% m7 Z# C; N
    # 定位head节点(元素)/ \; y6 Q/ W5 i$ @
    result1 = html.xpath('head')3 @  O+ m+ n% N; y$ ]& g
    print(result1)2 d7 v% p+ L/ e$ Z
    # 定位title节点
    ' z% }- x) ^7 t9 Wresult2 = html.xpath('/html/head/title')8 `; \3 ^* ?/ c3 B0 [
    print(result2)$ k7 u/ H, e- m9 y% U+ g
    # 搜索节点  title节点5 _/ I) t1 X  G1 R
    result3 = html.xpath('//title')
    - M* W! B0 O# {# K; mprint(result3), h4 }- `* @9 H* G5 K0 u. d
    # 搜索title内容  text()得到文本信息- v$ m' r5 ?3 B0 ?. J
    result4 = html.xpath("//title/text()"). r% n& Q% S3 ?# h
    print(result4). g# _# @' J' |% z2 V
    # 搜索div节点& ?4 A  k2 Y9 v
    result5 = html.xpath('//div')
    ( F; v  |+ ~. zprint(result5)
    : o/ k) \% t, n3 \  D$ n# 搜索div节点 并用class属性定位9 F6 Q8 ]0 S$ m; E4 @, Z7 i
    result6 = html.xpath('//div[@class="news"]')! ?/ W* E! L! O+ z4 M" r- D
    print(result6)
    4 J8 g% x+ K' @$ H! O: k# 搜索div节点 id属性定位; }, B9 c9 h" S6 M0 B5 y, Q
    result7 = html.xpath('//div[@id="news"]')/ k# l& ^0 Q7 A2 K
    print(result7)7 ]! R$ G4 P& e/ i
    # 获取列表span信息* u: T: q# Z; \8 W
    text = html.xpath('//div[@class="news"]/a/span/text()')
    / N9 e. T6 v7 y3 k6 {7 Bprint(text)
    5 I0 [7 o; j6 o0 j$ t; M/ D4 I2 g2 P! q& M" S

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
    . u+ {! G- d$ b1 G保存的方式有很多种:( u7 `( a* b( c0 `. t0 v# b
    1、保存至文件5 @0 g- M6 V! F' a* B( M
    csv、json、text
    + ~6 B4 s5 c% R  ]# R! a( Z2、保存至数据库
    - l) t' C" {5 N) qMySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍% t4 P; m% P; }* K8 s, x

    1 d* ?' L9 X/ p. I3 N! Y+ G! i% \# F/ r, o" I8 _) W# K
    ————————————————
    7 J! `' g9 d, z4 t# @: D1 B版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。- y: L- x  Q7 W5 `2 r
    原文链接:https://blog.csdn.net/royallucky/article/details/105930473( W! ]% J, b1 p3 W9 C

    ) V9 l' I; i4 d) c5 f* L. O2 a" F. Y" r" m) [9 L" }
    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, 2025-9-8 01:18 , Processed in 0.304720 second(s), 55 queries .

    回顶部