QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3668|回复: 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
    4 @+ P# m$ Q) P

    1 W! N/ h1 m  g; ~+ _+ J" y

    0 x! i" P  a4 N5 M' ?
    手把手带你5分钟搞定爬虫(聚焦爬虫)
    % Q$ ^3 A+ I: p5 D1 x

    ( A" p: c6 W( ~5 ^; n% Q爬虫的原理
    5 r* f6 K8 r- H) c6 V& I
    ( [6 b1 o, E0 A对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫
    + E1 W" }5 t* k2 a3 n; L8 w) d把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味
    0 p( C' c' V! J所以说爬虫分为三部曲:7 ], J9 v9 y" T4 U7 m  `, W
    1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)) a: O8 P3 s  U4 ?# E
    2、去找到你喜欢的食物的位置(得到目标地址), ]4 o  l2 R* M+ N4 `
    3、把食物搬回家去(解析网址,获取数据,存储数据)
    . u0 x3 u. [) G' B1 f6 }1 G* a它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
    . l) ^$ {0 l% W  b1 ta、导入需要的库 requests
    ( d  {) [8 L. |4 f3 b3 K' r# f0 @6 C5 Z0 [; u
    import requests
    ) {, H* s4 A5 C% V1
    $ l% v  f( g$ l  a* Z( @b、明确你要获取数据的网址(这里以百度网站为例)$ I; S, U! Z/ c( F7 c- e1 X
    ! l; k6 i: j2 Z6 g6 C; x# ~* b& k7 \
    url = 'http://www.baidu.com'
    5 {  Y& j  ]" q1( p& r$ H8 b! Z6 [  U) [
    c、创建请求% F0 g3 W5 `, J! |. u
    # j( l  f$ d# i0 h( P
    response =  requests.get(url)
    & K6 o+ w* C; t& d- L1
    * W9 H5 r: m& W8 P9 ud、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)
    7 S! Q" V+ q* o  S
    ; x% i+ U( ~5 @$ Pprint("状态码:",response.status_code)$ d4 P9 D- H+ B1 A% m2 j
    10 G: H. k0 r5 I' C4 Q0 G
    当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url# Q  `0 u( ]. G9 u6 D/ i
    e、得到网页源码7 j; D5 h1 }: F4 X

    + `) l4 m2 ]2 Z' K- Y, vprint("内容:",response.text)
    6 o( ~4 L0 V* _/ p3 N1
    # V: r# R9 K( ]2 a. f6 ?response.content是response.text的二进制形式& Y" @: |. I  d$ U2 R( N
    # M) ?: e2 p9 r4 p
    至此,一个简单的爬虫请求就算是完成了。
    # ?. W7 \: W9 G5 N( h当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据& e, U0 t1 u: N1 |; n+ x! s
    f、解析网址
    3 b: Z, G7 p3 U; y$ d刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用): r# A% u1 y+ d8 M" s
    BeautifulSoup:& I: A* U, Z0 Q! d- z3 B
    首先导入需要的库文件:
    * l& h2 {& i0 U! [! ]8 S. E/ b+ f
    # p9 n. ~9 m; F+ b5 Z$ g, `: ufrom bs4 import BeautifulSoup. T' ~7 I0 I  I7 l+ H
    19 S) c) ^. N/ h
    然后对上面请求得到的response进行解析:" W) I5 d$ u' B! y7 z' k) T' B

    0 P. _& r2 h/ Phtml = respone.content.decode('utf-8')
    ! |1 W& k$ o1 u' [: Gsoup = BeautifulSoup(html, 'lxml')2 E/ |3 U+ H. w' {0 |$ r/ ]+ X
    1
    . b$ b" U8 H) q8 ?" D2
    ' }' @% ~0 J6 q4 G, r9 J7 k9 v以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:# C; n) `  u4 W) q
    # 获取head标签
    0 a4 j) c/ w2 {; zprint('head标签内容', soup.head), l7 Y4 s7 [, r
    # 获取title标签# N& P- y6 K8 t
    print('head标签内容', soup.title)+ s# v3 ?3 j9 u8 i. ]$ D3 Q, j* A6 T
    # 获取body里面的img内容
    1 Z" n: B- ~  i) Z2 u5 ~# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
    8 ^4 ?. Z4 w$ x5 l6 ^9 dprint(soup.body.a.img)   
      _- b; a) h7 Y3 J$ A# 获取所有的img标签  使用find_all()搜索整个soup对象
    3 y, ]" m2 I9 u: P4 F1 Nprint("获取所有的img标签", soup.find_all('img'))' \  Y; V; o* s# y
    # 获取标签中的属性src地址7 o9 r* Q3 N1 n6 z. L% l$ S
    print("获取标签中的属性src地址:", soup.img['src'])      # 注意:英文点号都只能获取第一个值
    4 u$ t2 u8 E! A" ^0 U9 }# G0 Y1 H" N2 B8 I, ?5 Y1 n
    ) e* b0 w3 O1 i! H) w5 i2 l. T& u4 Z
    # 获取soup的name
    $ A/ ~! }) Q% r% M9 _print("获取soup的name:",soup.name)2 N# i* ~0 s9 s1 Y- p
    # 获取a标签名
      e$ s; H3 U; \# `( r1 K( nprint("a标签名字:",soup.a.name)  F$ K2 X' w5 A! {
    tag = soup.a" B1 }! y$ ]% i9 _- ]# [7 F+ r
    print(tag)$ I# T2 r% V& g- X; u
    # 修改操作  a标签改为b标签4 d6 Z2 }- Z" H' |0 p
    tag.name = 'b'   # 赋值后<a> </a>变为<b> </b>
    " r$ Y7 g3 L: _7 o# 输出修改后的内容
    - L0 O# x7 {# I+ W0 s' sprint("输出修改后的内容:",tag)5 y) y/ y7 F3 V+ U
    # 获取全部的属性 attrs8 b( a1 T* }7 _+ _! `( w% a
    print("tag对象的全部属性:",tag.attrs)   # 只能得到当前标签的属性(不包含下属标签)
    - H# t; N3 r0 t3 N, P7 ]4 b  `7 S7 B# G* G1 {1 u
    # 获取属性的class的值   根据键取值
    5 Y9 H0 b- \) h& Q6 e( fprint("获取属性的class的值:",tag["class"])
    3 c9 v: u/ Z& y5 ?9 J+ y1 b9 L1 F$ \# p) g8 r# K

    , s- R& ?5 H7 O0 z: _; L) |; D6 l% N; q  K; U# N$ g8 {

    1 e3 _! z. I8 Q"""针对获取的标签属性可以进行增删改查"""
    # Y+ D5 [* S. L  L# 修改& S( {4 ~, ]0 @- ^) v$ n
    tag["class"] = "Logo"$ v' c0 a; p" m8 D+ @: ?
    print("tag对象的全部属性:",tag.attrs)+ {! `( r0 e6 [& G" X6 v
    # 输出属性) b: h0 d& o5 F& d& K
    print("获取属性的class的值:",tag["class"])
    6 N$ \$ p: w! l# 新增  属性id  赋值logo2 x  ?9 Z3 Z: S: f8 T% l
    tag['id'] = 'logo'
    5 F0 ~' F$ l/ G4 Q+ n6 k# oprint("tag对象的全部属性:",tag.attrs)
    2 J! h. r4 `% n% u2 J6 E# 删除属性
    5 X% B3 Y* z4 J& U+ G2 A# Xdel tag['class']5 n& d: G  i% I" q4 E) V
    print("tag对象的全部属性:",tag.attrs)5 a' [+ S0 ?' \6 |: L8 L

    1 l) U4 y+ n) p: {1 W; O5 j. u& m. U( c' d5 W9 P, Y8 b

    $ p4 M6 P4 i0 O  J( D2 h"""针对内容操作  (只针对标签,对属性无效)"""* I# c; [/ e+ v( B
    # 获取title标签内容! O' |" Y( g1 _/ T' \1 f' J
    tag = soup.title5 |+ k/ p- ]6 F1 B; m% M. |
    # 获取title字符串6 y7 x3 i( h3 o% O
    print("tag对象所包含的字符串:", tag.string)
    4 ~4 X+ y$ o/ bprint("类型:", type(tag.string))
    : H9 b0 c0 m1 }; x* x0 ?# 替换内容
    ( Y; Y) }# Y5 N, @0 Ntag.string.replace_with("你好")
    . \$ N0 h; A8 m4 `: ~+ P' Z& y* Fprint(tag.string), q& s( H) u' Y
    # <!-- 学科建设 -->
    5 a' n) W/ C' R5 G9 }7 n8 x7 g# 获取注释文本内容4 ]' v$ X$ {! r, O& ^9 U9 {
    markup = '<b><!-- 学科建设 --></c>'2 [! ]3 d5 a4 q. o! d+ G6 R5 _% L7 K
    soup_comment = BeautifulSoup(markup, 'lxml')
    1 Y. c1 P: g0 G6 ]; Fcomment = soup_comment.b.string                    # 以markup第一个标签作为关键进行搜索9 g! l0 W6 H1 s, I2 o! G+ R
    print("获取注释文本内容:", comment)
    - T1 k7 O! |4 _) i5 H: O3 q# get_text()
    3 [: @6 ?- K; n% ]% Kprint("title的全部节点:",soup.find_all("title"))
    9 z6 k! y8 y$ M( E& s7 bprint("title的内容:",soup.title.get_text())
    3 y# q. @* Y. F1 Q"""查找ul元素标签"""
    + u6 `) R/ W, V4 @9 l7 O2 ~# class是关键名,匹配时后面必须加下划线_
    - u" Q$ W) {' p! |# z. L1 ?0 z% u: A# tag = soup.find_all("ul", class_='menu')  # 按照css类名完全匹配
    + m8 @; Y1 t2 M, g: {1 N- s0 t# print(tag)
    : |" {6 q6 p' H) Y& Z! itag = soup.find_all("ul", id='menu')  # 按照css类名完全匹配
    ( `9 F0 r* \1 A* aprint(tag); `& \% E" l. g, }" h2 m, i6 |8 e
    # 查找名称为a元素的标签内容
    1 T3 O9 L7 Z/ X' Z1 R5 rtaga = soup.find_all('a')
    9 |) D, C  W7 G7 o. P9 r  m7 n5 Ofor tag in taga:- A" Z* R7 o7 p! s- h
        print("查找名称为a元素的标签内容:", tag.string)) E: T/ g/ E6 ]/ ]* M
    # get 获取属性信息  获取整个页面的img标签图片和src属性值
    " G! d+ ?  L3 l# e' y* y# itagings = soup.find_all('img')
    8 u' c5 B3 U! J, Aprint(tagings)1 ^+ S$ Y- J8 r5 T
    # 循环输出图片地址
    / g- E' X# ~$ T% E; Rfor imgsrc in tagings:
    - R: I+ Q/ p' q8 f    print(url+imgsrc.get('src'))
    8 T! m* f8 q* L1 z( i) o. J8 L) R* E* k; t  ]& n
    """"属性只能做为参数,所有的操作只能针对标签"""3 d. A9 Z" T  m7 q" Y, l
    ' o3 w* `7 y7 D; N. }
    etree方法:
    ( g% W6 G+ |% |, g导入库文件:( k9 R8 e6 |7 i7 l4 R
    & m# N# @( W3 p- Q3 q
    from lxml import etree/ {( n. |/ M  U  C& m5 Y. G1 d
    1/ ^8 s: w/ S9 Z2 I) v; i
    解析得到的response对象;
    ' `% i! |* {! g( T1 Y% D4 k* Q& h- u# U2 r0 H; a% c
    # 设置response的字符集
    9 g! m% O1 T& thtml = req.content.decode('utf-8')
    2 D) Z) Y/ r4 U# ^# 解析对象
    # h  d$ l: z/ o+ a! B; `html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))/ \# {8 I0 q$ C% Y1 A' h

    : T: _& K: t' d5 D5 C常用的方法:
    2 o- b: j2 V7 y' k7 x' D, i* U& i3 J* H2 A
    7 c6 ?- e8 M& q
    # 定位head节点(元素)
    8 U7 R2 K! q- L& oresult1 = html.xpath('head')
    8 A: g, L2 O8 e) Nprint(result1)
    & j! K6 O" l" N1 F0 x! j% x# 定位title节点- W) N" Y+ z! U9 \0 p6 _" g5 Q
    result2 = html.xpath('/html/head/title')
    1 {# u6 b% g$ h' L7 Xprint(result2)  K/ n6 e0 Z5 q/ f4 U9 J
    # 搜索节点  title节点
    4 I5 y# l+ f3 xresult3 = html.xpath('//title')) H" N& u( E' [4 s' @: `; u- g4 ]
    print(result3)" S5 G* r1 E9 X" ^6 [
    # 搜索title内容  text()得到文本信息
    9 B) o) \. y- _- Xresult4 = html.xpath("//title/text()"); T7 D% G9 K& X% ^( n
    print(result4)9 F; a2 R( i9 }. ?
    # 搜索div节点
    , y6 a- I# ?- \3 }, Iresult5 = html.xpath('//div')3 l) t2 {2 H) D9 _2 Q- _) B- t
    print(result5)
    7 I$ C' a4 h" R, P# 搜索div节点 并用class属性定位
    ' f! |! h& ~( nresult6 = html.xpath('//div[@class="news"]')
    - {$ X4 |# h2 z. p% ?7 ]% bprint(result6)
    / y& o: p. j6 P& p# {# 搜索div节点 id属性定位$ R" ?% T+ q5 S7 x  q1 ~5 ]
    result7 = html.xpath('//div[@id="news"]')" F7 B  |) d' @. n8 \
    print(result7)
    : S# ~: V9 u' _1 c! c: r$ d  R# 获取列表span信息
    * ~, t$ d+ c7 m! S4 Dtext = html.xpath('//div[@class="news"]/a/span/text()')# |# `. `# d" S4 b$ d# R( g
    print(text)( o! X  ?8 Q' Z" ?  G
    : C. i; ?9 `8 t/ u! ?( a  M8 j

    g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存/ w2 S# Y. W9 E& B0 @6 B
    保存的方式有很多种:; j" X6 s5 ^' p
    1、保存至文件9 T+ K' {1 t6 p6 R( B7 Z
    csv、json、text' H5 u# T1 ?# O* j3 U' `8 t# b
    2、保存至数据库; v1 \4 V- X9 a9 Q
    MySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库)

    关于数据存储后面再做详细介绍& d1 q2 \9 v6 Y6 J9 Y: d9 k

    9 L9 E* H" V* E) ^& l) E% r# K4 @/ ^5 X% C1 Z0 o2 r/ G
    ————————————————- ^0 y6 n* w' g$ \
    版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    . L8 l% ]& f! L  Y原文链接:https://blog.csdn.net/royallucky/article/details/1059304732 r: W$ d% [( }/ N6 V0 s0 f: `
    4 k" i8 i9 A6 x* a# Z; W# H

    ; x& r7 b6 t; V" t; 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-4-20 06:01 , Processed in 0.356101 second(s), 55 queries .

    回顶部