- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 564697 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174632
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
" B- b+ ?9 E2 j
' B$ v+ Z# r; o! x/ H: m
7 F% E3 A: A' W# n( {4 M8 C/ A
手把手带你5分钟搞定爬虫(聚焦爬虫)
, q, Y) O/ @/ Y8 E# I4 \% K3 Q' {, X6 b; Y' J3 ]0 J! X, p
爬虫的原理; v! q8 a7 a( Q, W! a, n; S/ a
% i! y2 p Z+ H9 V' ?对于很多刚入门的小伙伴来说,了解爬虫的工作原理是非常重要的。只有当你了解了它的原理,你才能结合实际情况写出对应的爬虫。下面我将以通俗的语言方式来介绍爬虫+ [. T1 T) V4 A% T4 U
把互联网比作一张巨大的网,那爬虫就是这张网上面的一只小蜘蛛,在互联网上面有很多的数据,各种各样的数据,我们可以把这些数据比作是被网粘住的小昆虫等。爬虫的作用就是去找到自己喜欢的口味,然后把它带回家,可以储存起来,也可以马上享受美味( @0 H2 K( ^' m$ k, R! j6 Q6 ~5 B' s
所以说爬虫分为三部曲:+ K0 _ v9 Y, {/ Q& L5 {, e! c9 ~3 l
1、明确你自己喜欢什么口味(制定需求,明确你需要的数据类型)
% t# k: C4 z3 b) g4 Z2、去找到你喜欢的食物的位置(得到目标地址)
7 ?8 ]" _& ^5 B' F) p' E3、把食物搬回家去(解析网址,获取数据,存储数据)
; s; T( ]" D% x它的整个流程就是:(简单的通过request请求获取数据并解析获取数据。以下都是固定化格式,可以照搬)
+ ]% h6 C5 F1 C5 wa、导入需要的库 requests7 y; Y/ n5 ?# z0 t+ z, }, }
8 I& O5 Y y p& E' N
import requests
6 _8 L B+ a$ i. J" K# @# B- I1 R* S: p2 U- T: r9 M
b、明确你要获取数据的网址(这里以百度网站为例)
+ g% e: s s" z8 @
n& M, b7 ]% e( ^4 j9 Y9 Iurl = 'http://www.baidu.com'1 U" F9 k' Y L: T! y# N# B* l9 I
1( k0 z0 k N. Y) z6 `
c、创建请求
+ v j. A- ^; H. r2 }, M& o5 F a7 ]% x/ f6 L1 h$ D: H8 R9 h
response = requests.get(url)
/ L$ f0 f: I+ p+ s16 v0 P% L8 u' L4 v
d、测试请求是否成功(在实际应用中用的比较少,正常情况都是可以请求成功的,网站对于访问外部信息的爬虫是不会做出限制的)* s+ m" L7 P( k4 @
$ l) X0 ~! Q9 }) V& bprint("状态码:",response.status_code)
2 w* K$ Y- A! t) M+ A4 S0 B1- v" @9 m, a4 I6 y
当状态码为“200”时表示请求成功;如果不是“200”,很大可能就是你的目标url写错了,核对一下url5 O! Z4 D. V9 r8 L8 i+ x+ T& `
e、得到网页源码
6 t& ~* N5 u( u, ? H, N1 P0 M
/ N, _; X. d# R& Q# U6 S) Mprint("内容:",response.text)0 f( i# m% K; x7 t" i
1( c& {$ o" I; d( P3 U; Z, l
response.content是response.text的二进制形式' i. z1 R! t: `& @' B1 |; O
q1 u2 U, G- Z$ S. \
至此,一个简单的爬虫请求就算是完成了。+ c n: V: t2 L
当我们请求目标url并获取到response后,就需要进行下一步:解析网址并获取数据
2 X& f) i8 [7 O+ Y) z) [f、解析网址, x4 i# X& a2 \( p+ B& G, B
刚开始学习阶段,我们最常用的两种方法,一种是BeautifulSoup,一种是etree。其中BeautifulSoup是最常用的。以下将对两种方法分别进行介绍 (以下方法均为测试用例,实际当中应结合自己的实际情况选择应用)
) N" N# c7 C# vBeautifulSoup:
: B; [. x) B: K首先导入需要的库文件:2 c0 i; m3 B. F, \6 a- P9 S
3 a/ p1 v; N( L$ m% J5 {
from bs4 import BeautifulSoup
' S# o* H$ p" G/ c& D/ P9 H1
7 J$ c- J. ^* v* R; o0 K( g% C) Q然后对上面请求得到的response进行解析:
$ h5 s2 `' V+ O
, V0 p a7 O" ~. ahtml = respone.content.decode('utf-8')- F5 r6 U! \" E4 Y
soup = BeautifulSoup(html, 'lxml')1 k) Z7 l7 r. v- o
1
2 P) x* e( y6 ^2% y& N* F# R8 E) G' X9 f
以下是BeautifulSoup中比较常见的方法,有兴趣的朋友可以去一一测试:
% p4 @& i% o) N! ~) q9 K# 获取head标签, H, B0 t' }' ]& f
print('head标签内容', soup.head)# k E1 V" [1 c
# 获取title标签
. E9 s) L, P7 j% \1 Uprint('head标签内容', soup.title)2 ^$ W) A$ K8 t& k0 D e) P. \
# 获取body里面的img内容" ^( y4 n$ s5 f: o$ N/ O; `
# 通过点号的方式只能获取 下属第一个标签(即获取soup下面第一个body里的第一个a标签的第一个img标签)
/ I+ e( l9 `* c _print(soup.body.a.img) 0 [# V+ K( ?1 O# _0 D) i( `. o
# 获取所有的img标签 使用find_all()搜索整个soup对象
+ ~) H1 C) I9 { N* aprint("获取所有的img标签", soup.find_all('img'))$ @3 u( c0 N! d L& g
# 获取标签中的属性src地址" Z9 k+ G0 C( _1 b( y& f# B! x
print("获取标签中的属性src地址:", soup.img['src']) # 注意:英文点号都只能获取第一个值# n& X( Y k0 r1 T M% b- T
8 z! @( H7 m( @, I- H
# p4 W! _4 n4 p# 获取soup的name- |! \& s, @; b1 M
print("获取soup的name:",soup.name). A. O, ]% R! p; g
# 获取a标签名2 r5 s; ~. O- j& R Y$ c, P7 F( j
print("a标签名字:",soup.a.name)
1 y# M+ C. \8 Q, J3 M V8 etag = soup.a v- W2 ?) g1 g5 [3 ^0 y
print(tag)% L: N) Y5 T" P- R2 |
# 修改操作 a标签改为b标签+ \2 A4 L1 _. V+ A8 [0 f; u
tag.name = 'b' # 赋值后<a> </a>变为<b> </b>
1 e3 ^: `& ?0 J( h ^# 输出修改后的内容/ m/ v' l) {# R3 L
print("输出修改后的内容:",tag)9 b ]( r9 D. d" D' e [# K! \4 d
# 获取全部的属性 attrs
7 D- W9 x# F; tprint("tag对象的全部属性:",tag.attrs) # 只能得到当前标签的属性(不包含下属标签)! j0 X* ?4 ?/ M Q* z+ N
" t- Z3 ]+ R2 {& A7 i: W1 H# _
# 获取属性的class的值 根据键取值% P- v+ s9 _; x7 `
print("获取属性的class的值:",tag["class"])
* Y, z4 o8 v, @0 U3 n' X2 c. F% T9 |* t7 ?& j
1 Z5 A0 n/ g, |+ |! W7 d8 y, r
5 o' b: A7 s9 R' B4 `
# f. s6 U" ~$ L9 D' {"""针对获取的标签属性可以进行增删改查"""
4 D1 l$ Z) w" h+ C# 修改) D7 p I: W: y2 q: n9 m$ b, t" n2 {
tag["class"] = "Logo"
0 y- W Q% I4 fprint("tag对象的全部属性:",tag.attrs)
, x/ V' |2 x) }2 O5 P& g$ e# 输出属性
7 S1 z, `2 p8 Q5 l9 [$ v! vprint("获取属性的class的值:",tag["class"])4 J9 z' R+ s' W9 i8 ]
# 新增 属性id 赋值logo7 w2 S3 @- p0 _
tag['id'] = 'logo'
+ x' `; a# L S$ M) rprint("tag对象的全部属性:",tag.attrs); L* ^$ ]: Z8 l+ w$ X W, ^
# 删除属性
F8 S Q) r& G" x1 G2 E6 b9 ^del tag['class']
; G8 G1 l3 L( |( a6 A* Yprint("tag对象的全部属性:",tag.attrs)3 u: N4 @2 C; M# `
/ w9 Y7 @; v9 W$ i. r3 i H% d( R( W5 u8 q8 I0 a$ c/ F
2 ]0 d, P# e; D. X9 _) W"""针对内容操作 (只针对标签,对属性无效)"""7 p( Y0 e. w* P/ n; B# B
# 获取title标签内容% U6 c% m" r1 E, W1 i4 \
tag = soup.title
3 b0 V; S( T" C* T" V, x, V# 获取title字符串0 i/ n y( [* }4 C# D- s+ V0 ^
print("tag对象所包含的字符串:", tag.string)
" v) }( d/ o2 b/ U0 bprint("类型:", type(tag.string))
7 f( h" U8 m0 {6 ?# 替换内容# c0 ]8 D& D S2 Q# E9 d7 |$ {
tag.string.replace_with("你好")$ I$ [) D$ J3 e0 c0 d' v- @
print(tag.string)% K% i. m& R% y4 V
# <!-- 学科建设 -->
: }. O i3 Y* z* {# 获取注释文本内容
( w( M3 W3 W7 T& g. J5 s& }. [markup = '<b><!-- 学科建设 --></c>'
0 \/ I! [/ |) v" J' ]" `soup_comment = BeautifulSoup(markup, 'lxml')' e! F! O2 w" ^
comment = soup_comment.b.string # 以markup第一个标签作为关键进行搜索 ~) n" A- X) l1 G- h
print("获取注释文本内容:", comment)+ }; \( @) P6 R* w/ @
# get_text()
0 U7 K1 `+ ^, M. q* jprint("title的全部节点:",soup.find_all("title"))5 R0 I3 H+ c0 v! {
print("title的内容:",soup.title.get_text())
. b l6 `# K4 q; H"""查找ul元素标签"""
|" |; ^7 T+ }, F# class是关键名,匹配时后面必须加下划线_8 I% P9 n$ M$ i2 \
# tag = soup.find_all("ul", class_='menu') # 按照css类名完全匹配
* t# n# T* h5 k; w. C4 H" \# print(tag)
9 e, U% N1 M6 G7 }0 A0 Ltag = soup.find_all("ul", id='menu') # 按照css类名完全匹配3 T( e0 i4 s$ X7 y! p. y' ~! g
print(tag)
& p# P" x" V: _# 查找名称为a元素的标签内容
) v/ o$ P/ z$ ^' U3 M0 Htaga = soup.find_all('a')
7 s2 p" u. v" C# afor tag in taga:
5 m) B5 a# b8 P print("查找名称为a元素的标签内容:", tag.string)
5 `0 p# V/ g( H4 \# get 获取属性信息 获取整个页面的img标签图片和src属性值
& P" @( N+ \0 w+ B5 [' h. t& t: Ltagings = soup.find_all('img')
; I! P" @ K) g! Pprint(tagings)4 g# {' k; N8 N' O% r$ k
# 循环输出图片地址
9 M h8 w6 S1 j# J" vfor imgsrc in tagings:
6 |- [2 E& ?; e. j print(url+imgsrc.get('src'))
, |* n. q; Y, e' L- _- `, G# }* [8 t
""""属性只能做为参数,所有的操作只能针对标签""" c; g, M6 |: d. {; p& w. i
8 L# E1 d2 N' @( R7 ?
etree方法:
- j3 \6 w l5 y Z9 W+ [) E6 p导入库文件:
% F* r& S3 }2 t; M) }* b& c( V( w- P4 R
from lxml import etree: E" Q9 O3 S# B1 D0 S
1
6 u% t1 h& O4 B" }( i4 U7 d解析得到的response对象;
% \% o4 o7 V8 d. R$ Y
: A/ y F9 ]8 h3 w; j+ i. c# 设置response的字符集
" n: K( x1 P- Q$ T2 ]; F5 ~html = req.content.decode('utf-8'): o7 L) z6 x$ ~ j; N
# 解析对象- P7 \$ I7 v6 a t! V7 J4 }
html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))% G6 y/ U1 Y3 U O. E% K
3 h( m) [! V" |4 X0 I- S常用的方法:/ n* L0 p# D) I5 V0 p
) Z' q1 W: g( y, K6 ~9 c
4 } U/ { a9 G8 Z" g/ j. ]) [
# 定位head节点(元素)
. P: [. j- ?: A) B, U) n' z: presult1 = html.xpath('head')
+ L$ B5 U) d: a+ V6 tprint(result1)
! i5 K$ G; |9 _- X7 Q8 k- V2 t# 定位title节点
7 b! `" ^0 F9 D4 H7 r; R. cresult2 = html.xpath('/html/head/title')
+ @* w( f( z7 L+ t5 Qprint(result2)
- |: g5 }0 v" R( t+ q' E# 搜索节点 title节点, L! ?+ F8 @- D6 w1 _
result3 = html.xpath('//title')
' s3 C2 M+ Y3 n8 A% Z' l Mprint(result3)
; h! y2 F& a7 H- b4 ]. h1 {# 搜索title内容 text()得到文本信息! N' w( v3 z% i" Z
result4 = html.xpath("//title/text()"), L# U3 j' a7 z. ~* L7 ^
print(result4)
& ^0 v6 v/ s9 h6 p P# 搜索div节点
& {) Q6 Z9 m1 r ]) L* c# Mresult5 = html.xpath('//div')) f- z) U! e0 A8 q
print(result5)$ ?2 a% x9 y( y
# 搜索div节点 并用class属性定位( _! [( c7 M: [ G
result6 = html.xpath('//div[@class="news"]')1 `- L& O. z; O5 C& R) E) P
print(result6): N( x$ M5 G. Y2 y& J' a) O
# 搜索div节点 id属性定位' g3 f4 y, K/ K2 b; S- g
result7 = html.xpath('//div[@id="news"]')
, b: |% H- ?5 T- jprint(result7), n- K" ]. {9 k6 u( l) O
# 获取列表span信息6 H" ]2 n: e P* |) B
text = html.xpath('//div[@class="news"]/a/span/text()')
* e6 V/ r" R6 G. y, nprint(text)
; m* a( Z6 g6 J) o3 D& f
6 ]) _, D5 F& `g、通过上一步我们得到自己需要的数据后,下一步就是将我们得到的数据进行保存
6 s$ S6 G- n2 a% U% i8 w保存的方式有很多种:
6 E( s0 m) ]% C# n8 j7 P" l/ E1、保存至文件
[/ E2 x7 y6 W& y7 T& Zcsv、json、text- n/ O# T7 `0 f" ? q$ R+ l* l0 l
2、保存至数据库
# V+ z5 E* v# H2 p! o! w ~$ g; dMySql、MongoDB、Redis 等 (目前主流的为以上列举的三种数据库) 关于数据存储后面再做详细介绍
5 E* X Z$ S" Y8 O3 Z
' |' d" o, \" V
6 t8 i \ U% N7 H6 L1 S————————————————& d9 I% ]2 l3 D0 R! }
版权声明:本文为CSDN博主「royallucky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。7 N9 z/ u" w/ r9 t m5 J
原文链接:https://blog.csdn.net/royallucky/article/details/105930473
! B+ n4 p, T7 |3 O% I4 t1 Y$ i+ R, c; ]
; Y( u" l8 ]; A5 y8 \: G& T |
zan
|