基于Web的爬虫系统设计与实现 4 x/ h5 ?7 O! N6 v7 G4 g& Z( h ) X& r! Z- w( z* _. Y$ h+ A全套资料下载地址:https://download.csdn.net/download/sheziqiong/85585280 6 q5 d( @) y0 W; i$ q1 \全套资料下载地址:https://download.csdn.net/download/sheziqiong/85585280 , R0 d! ^, W& q2 C V k8 b3 n目 录 1 @. ?4 {& o. X' ~1 绪论 1 q# t- T% f1 f1 a& d# Q* o. P- U
1.1 选题背景及意义 1$ i7 ?/ `1 l1 \7 H* N
1.1.1选题背景 1 . B, q+ `( h! E6 V; ~1.1.2目的及意义 1, ?" x4 |$ ]# S2 Q
1.2 国内外发展现状 2/ w3 _7 [5 C. H4 ~0 s) O
1.2.1 爬虫技术概述 25 }; Q V: K) w% {/ o) o3 m2 I7 w1 J
1.2.2 爬虫设计者所面临问题和反爬虫技术的现状 4 # Z. \5 |% X ~" ~1.3 研究主要内容 7; H t! R1 w% w. ]; W& ^; E
1.4 章节安排 88 S P8 g) h1 ~& k m' C+ {
2 系统开发环境及技术介绍 9 - x' |5 K% J; s' @ q, v0 K2.1 Robot协议对本设计的影响 9 3 i8 z* d# j4 X) P: A2.2 爬虫 10 6 }, S" [$ ^8 r2 H4 q2.2.1 工作原理 10 , ~# w+ c) S* T' _1 L3 g8 `2.2.2 工作流程 10 . z1 u1 N: ~9 p ^2.2.3 抓取策略 10+ D+ X0 r6 m* ]5 J6 b
2.3 Scrapy架构 11 ! P# m r; S) z7 R2.3.1 Scrapy:开源爬虫架构 11 : b( [& \, B# \0 V E2.3.2 Scrapy框架结构 11) J; A4 z/ i, t% e. }2 I2 m
2.3.3 两种继承的爬虫模式 13# O. g4 W, {2 I( d5 n
2.4 MongoDB数据库 14 0 _# i* k( T0 a3 h M2.4.1 NoSQL数据库介绍 140 r: D2 u2 z9 ]" m O3 Y
2.4.2 MongoDB数据库介绍 15 # {& B3 l/ u" w& p$ l6 Q2.5 python web框架Django 15 + t5 x* e4 f4 d5 ], I1 m2.5.1 Django框架介绍 15 V3 d3 [2 R/ {( ^7 E) I, c8 U2.5.2 MTV模式 15 . Q, m4 F* S7 B' J! f& ~' K# E2.5.3 ORM模式 15* O* }# f% F* x; L
2.5.4 template模板语言 16 3 t7 v% w2 B0 ^0 J3 K2.5.5 Django工作机制 16 3 b* n1 b" I' s: N0 A2.6 semantic UI开发框架 17 E7 i3 B V3 N0 L+ e! f9 q2.6.1 semantic介绍 177 p: v+ J$ [- A# v
2.6.2 semantic开发 177 k8 {4 C, g2 m" }: s/ }
2.7 高德地图API 17- l2 P- Z& B# E) j O
3 可行性分析及需求分析 19 5 P% {6 F5 u" ^3.1 业务需求分析 19: ~9 {% X6 p! ~) ^' f
3.2 功能性需求分析 195 E! _' h& U, d. R% W+ I+ K' h
3.2.1 数据爬取功能 19, \1 V* n! r8 W# M ?
3.2.2 数据可视化功能 20( X1 ?" O9 T2 X9 P o
3.3 可行性分析 21 5 ~" X3 O; D& f& v: f" r2 E% y* o* G3.3.1 技术可行性 21 ; q, s8 F: e0 F: O3.3.2 经济可行性 21 . q+ e5 Q0 _: C* ~. Q% l3.3.3 法律可行性 225 P% Q1 Q9 R+ x. h
4 总体设计 238 s0 @, [% w) m4 W7 @; u
4.1 系统逻辑层次 23! b3 p+ O4 H3 e" _+ L3 P
4.2 系统分布式设计 24; ~" u, I5 q- r9 C+ g1 B
4.3 系统功能设计 25 7 V' F7 s2 ^5 F. h. _4.4 系统数据库设计 26; V& D: n2 Z0 M, q: P R
4.4.1 数据库环境搭建 26 ! B/ ~- s5 Q( w- t4.4.2 数据库表设计 276 C- `; s" S$ c8 E% a! ]4 W
5 功能模块的设计与实现 28: k, ^% c7 q' e4 t5 c q
5.1 数据爬取模块 28 , q5 K/ W: y2 _7 k/ Q/ l5.1.1 爬取策略的设计 28 / m! E9 I/ K3 f5.1.2 网页数据提取 304 T/ M* s8 w# a) E1 X B
5.1.3 去重与增量爬取 32 3 ]" D1 {. ?. }+ }. l5.2 反反爬虫模块 33& u3 w- a( D' ]* \2 m: x" \# \6 L
5.2.1 模拟浏览器行为 33/ k g' R; ^" L `/ J
5.2.2 动态代理IP 357 F9 p* G8 j. a
5.2.3 爬虫异常处理 367 Y: x2 R/ v% l# _! ]* N" J# n9 d9 J
5.3 数据存储模块 377 z) i! N' d% N ?2 F G
5.4 数据可视化模块 38 " @* ]: N2 v7 c% x1 s6 功能模块测试 42" b% |/ H# i7 q1 X) t* Y' [: S4 w
6.1 测试环境及工具 42+ [3 B# [ M+ E' K, ?4 k
6.2 系统功能测试 427 i$ i' W$ a4 ?% H$ e/ n, |
6.2.1 数据爬取功能测试 42 + T j! B" |. ^, V6.2.2 数据存储功能测试 44% I& {+ D T7 q
6.2.3 数据反反爬虫功能测试 46 % j1 W1 j/ Y; i# _6 \: v8 O% `4 r6.2.4 数据可视化功能测试 477 N& b; {# k+ \8 [+ Q3 v3 J7 @
结束语 48+ x7 s7 n9 u; ~$ X3 y
参考文献 49 0 n- K$ `& q+ j0 v" b致谢 50/ @: T) b; k; s V7 X% e
3 可行性分析及需求分析 2 p. R2 B7 ]1 ]5 Y& F- c* x3.1 业务需求分析 7 p; J& y4 J& T: ^: v; j/ S本次通过对链家网广州二手房房源网站进行了研究分析,目标实现一个房源信息爬取的系统。本系统被用来解决互联网上关于房源信息繁杂,房源信息分散,无法通过短时间的用户浏览获得所需要的所有数据,其房源推荐系统数据来源严重不足等问题。本系统的目标是将链家网广州二手房的房源数据爬取下来,存储为较为干净的数据源,为房源推荐系统和数据分析者提供房价分析所需要的数据。5 r/ f/ W9 `+ h) \) o
本系统的基本业务是围绕二手房房源信息展开的,应该完成的基本业务功能应该包括两方面的内容:" H! H$ s, T- X/ W# e
1.系统需要爬取链家网上的二手房房源信息 1 j& I% d- O, s& P Z4 M0 B% l本系统本身并不生成房源信息数据,它所获得的房源数据来源是互联网房屋交易网站链家网。因为链家网并不向用户开放自己的数据库,所以系统需要通过爬取技术将来源网站上的所需数据获取得到。 4 A* b1 H) T- A }- ~0 j( k7 \ X2.系统需要对爬取到的数据进行数据可视化 % G, P% x6 R4 y0 Z4 o本系统获取到的数据是存储在数据库中的,当需要对爬取数据进行查看时,特别是爬取到的房源数据量很大的时候,数据查看很不方便,而且数据库浏览界面太过单一,无法突出数据特点,所以通过使用界面以数据可视化的形式将爬取到的房源数据展示出来。 ' F7 H2 G' x! x. m5 A/ O3.2 功能性需求分析 @1 U2 C5 s5 \% G% c$ c+ d9 m3.2.1 数据爬取功能 5 n7 ]0 {, T3 `# j x数据爬取功能是指将房源信息数据从数据来源网站爬取下来的功能。本系统是面向二手房信息的分布式爬取,原始数据来源于链家网广州二手房。分布式爬取是使用一个Master服务器和多个Slave服务器快速的对网页进行爬取,加快爬取速度和效率;Master端负责对目录页中的URL进行爬取和存储,Slave端负责对详情页的URL进行爬取和存储。' E3 {. U) E- p& H
; i' g. e, D' v g1 K/ r5 H- eimport scrapy' k/ P: V3 A( a' X+ a
from scrapy.http.response.text import TextResponse2 M; {7 ^$ t+ R/ x" }
from datetime import datetime + J3 W' `2 h. C3 p0 h: b: [import hashlib+ Y( G5 f6 b3 P0 }8 C* x
7 p7 Y$ v- S* n* R) j- Nfrom scrapy_lianjia_ershoufang.items import ScrapyLianjiaErshoufangItem / l8 B1 c/ R. O) ^# |' U# N7 } ; e. r0 u7 h0 h8 s3 g. E- L' X* M5 L! b6 X( `3 S: m
class ErshoufangSpider(scrapy.Spider): , I+ d9 l! W7 U" B) g name = 'ErshoufangSpider' / t% R" ^& X" [, j8 }5 m' r" S2 ? T- f4 y6 x$ k2 }0 w
def __init__(self, name=None, **kwargs):2 M0 n! h. b- Z$ `* n
super().__init__(name=None, **kwargs)0 T$ {# T# r4 S @ ~
if getattr(self, 'city', None) is None:* O) g/ t* b8 r8 Y% Y
setattr(self, 'city', 'sz') 9 a- I: X! q+ @ self.allowed_domains = ['%s.lianjia.com' % getattr(self, 'city')]+ x& N7 A; h+ Q& J0 M9 q6 ?% ?3 O
! ?$ |' B8 [" ^ def start_requests(self): 8 }2 n/ m/ M, S. {7 Q$ l city = getattr(self, 'city')! U( { x" U S1 f) y# g4 w
urls = ['https://%s.lianjia.com/ershoufang/pg%d/' % (city, i) ; k% U; L1 D: K) G4 f. q/ E for i in range(1, 101)] % U) u* x* p3 M" W1 f1 R- i for url in urls: , ^' K' @/ B. i; G2 ?" W, o- ^ yield scrapy.Request(url, self.parse, headers={'Referer': url}), L) Z, i: L: L* R
7 a* U; f# H1 k5 g$ [ def parse(self, response: TextResponse): 4 y. w- J$ h P2 U1 Y9 l items = response.css('ul.sellListContent li') 3 Z2 V3 g4 }9 P6 a for li in items: . j3 J2 }4 Z$ z! R; r9 _# W item = ScrapyLianjiaErshoufangItem() " W0 \7 v7 {# E7 N2 P item['title'] = li.css('div.title a::text').get().replace(':', '').replace(',', ' ').replace("\n", '') : w" C" ?1 `0 y9 S; ^$ |2 }: d house_infos = li.css('div.address .houseInfo::text').re( 1 e7 K& ]. Y4 X+ \' g8 U r'\|\s+(.*)\s+\|\s+(.*)平米\s+\|\s+(.*)\s+\|\s+(.*)\s+\|\s+(.*)') * o/ ] y- U. b$ b9 g% L item['room'] = house_infos[0]/ H7 {! i: r$ p
item['area'] = house_infos[1] ( A, ` M) v5 c! R5 J$ B* P item['orientation'] = house_infos[2] . {- }5 j5 R% Y! I item['decoration'] = house_infos[3]9 z) k# O0 l- l" y) u0 j5 S+ `/ [
item['elevator'] = house_infos[4]; E8 ~: C1 o# g6 s$ S8 d4 U
item['xiaoqu'] = li.css('div.address a::text').get() & |9 O1 O. K/ h* s item['flood'] = li.css('div.flood .positionInfo::text').get().replace('-', '').strip() ( V* s8 Z; T; P item['location'] = li.css('div.flood .positionInfo a::text').get() 8 `$ j7 }+ h6 } follow_infos = li.css('div.followInfo::text').re(r'(.*)人关注\s+/\s+共(.*)次带看\s+/\s+(.*)发布') 8 J6 O6 k0 E# ]2 m7 q" h item['follow_number'] = follow_infos[0] & H4 }8 K1 l6 t% ~- ?& h* k5 J item['look_number'] = follow_infos[1] ' ~! U1 c$ m. @ {3 S item['pub_duration'] = follow_infos[2]! x% B; J( S& f# ^- V! w
item['total_price'] = li.css('div.priceInfo div.totalPrice span::text').get()6 B5 A9 ]5 ?* Y, n6 a; g! C; ^
unit_price = li.css('div.priceInfo .unitPrice span::text').re(r'单价(.*)元/平米'). ^& i+ p4 L8 G D( W: ?# ]
item['unit_price'] = unit_price[0]+ u' k1 T5 S O0 v
item['total_unit'] = li.css('div.totalPrice::text').get() % ]7 l {) e% l item['crawl_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')/ I6 ]* k# U# P$ N/ Q7 l' V
item['house_id'] = self.genearteMD5(''.join((str(item['title']), str(item['room']), str(item['area']),9 a( s- V ~7 ~9 M; O* i& D
str(item['orientation']), str(item['elevator']), 9 B5 j" B+ _ {9 A* _* E7 G) |3 Z1 \ str(item['xiaoqu']), ]% O5 W1 e. L' r0 a6 \" L str(item['flood']), str(item['location'])))) 1 E6 ]/ c. z6 ]# R yield item # L- T) N y- \6 {4 h2 \. `% }" o" p) u6 W
def genearteMD5(self, text): 1 B! y+ n# U! T8 o m# z# U # 创建md5对象" e3 o5 y; `9 f
hl = hashlib.md5() : @* o7 ?5 P2 @, l7 p& R4 d$ w hl.update(text.encode(encoding='utf-8'))7 W: v2 s4 \; a; d, K6 F
return hl.hexdigest()0 z( h: @$ ?+ f
/ l* |1 k- p9 x* r" i- e. \4 G" r3 Q. j
1 . H# |$ G! l a+ P21 i! ?( f0 U" u% ]
37 ?) b9 z- O1 Y6 D e
46 C! Y. p g1 U) R
5 & M5 Z4 Q |6 ^" W" d61 F8 }1 P* _. z
71 F9 T7 D$ Q) w
8 2 [# Y6 q% s3 T6 b: E95 e; ?% {' ^; a S5 `, S2 q% I
10- J3 P0 ` o# x% L% i, }
11. u0 @6 K4 C' A2 v5 ^# t
12* B; J- ^( R' I+ e/ K1 T% Q& ?' L
13 q0 ] y9 i+ I4 p3 W14! s- l8 h- j6 X: n4 \0 h6 C
158 V# I9 ^$ F( s! C u
16! [5 T- m$ [/ O. [3 B' U- R
177 w- |4 I8 z, V& v' ` \7 }
18 8 i$ _4 I# L! u7 \' t4 {19. X+ _6 f ?0 |, `. a ]4 D* f
205 @6 p8 v3 c' @. O* m8 a6 @
217 E+ W4 H! S) H1 E2 R
227 R+ I& {9 v9 \* h
23$ \7 \0 R n c# r
24) X$ ~) V) {; U) R. s) M9 n, J
25$ D9 ?. \7 g3 m- M: y
26 $ J% w1 x. D1 L7 l27% B$ W# m: l# P
289 }1 R& j/ c; F; O" s# H* S
29% v* T" H( O0 t
30 / p3 }. y% m* K# b2 [312 h1 k* k+ r2 s8 z" u& ~& l
320 ?4 W7 D. K, m8 Y2 r$ e: s
33, e8 n% |! i$ d" B l t) V' B
34 % r3 Z) e% `8 N1 R1 R5 a356 y. a# Z s/ p+ P6 F1 `
36 , p2 [* R K7 f37; J- c5 [. [5 n# \4 D. O
38 1 U7 p8 j6 |# U39 S" i& j% j) [; x8 v7 c) D40 ! x3 q+ u+ [- v' X+ r41 ) P+ n- h' ^2 u5 q! l42* m' A& y* v! A. f7 w) f5 s
43 , N7 }7 u& a$ D, b( @# i44 ) k {0 J/ _: }/ g! a8 x$ V45 ; [* f c- m' k. ]) S! n G+ D465 K# B5 h) y; O x' F; m4 L; f
47 & ~6 a( @0 _# j, B2 r6 d0 |48 " |/ |$ R& E. q' F49' Y! Q1 [2 A7 A0 S( E) d. q
50' C1 Q/ `" A7 C! `! c# }% S4 J3 Q
51 % \+ r% o5 h# _; \1 S52 6 ^1 e7 \) ]7 g6 h* i7 d# W53$ Y% z; K6 h2 @$ _1 g
54 & |; x2 k" Z }) m: U3 ^7 k55: D7 M5 S5 W& F5 a4 G
56; e6 l* \2 X& m! Y8 e$ }
57 2 A, h# Z' o3 c$ O6 ]! L4 B/ k58 4 M$ }( C6 }% d @594 Z# [: g8 ^! N( ~- U. d
60 + n% g I+ \: i - n$ g; t$ d; g% A/ y, M( |+ j1 `+ }/ ^3 l
. I4 k" m$ d- Q& I; u2 C 0 Q* p2 Z) v) y( h2 N0 K1 Z3 x( e0 \9 B) e8 b- k! L L7 |, [
( |" B# r) b/ |' x
& {" w' B5 k: G2 U& x
e$ }. V; }! c5 n4 W
7 ~' d, `2 _- K& N- l ; G/ `3 c0 g: X - K* }6 x& A6 b 1 g- R9 k& r+ z: i( l5 j7 g( L3 a i: p+ T1 y' K p
) { a$ b0 v- n9 w- q 8 @5 r* T2 f# H! a & N: r7 n, ?: g. P& b6 ?全套资料下载地址:https://download.csdn.net/download/sheziqiong/85585280" I# i) k# @' |* C2 f( P
全套资料下载地址:https://download.csdn.net/download/sheziqiong/85585280; Q: Y; l* C, w0 x* I4 h3 D7 P0 k) h
————————————————3 n9 c+ g/ @* w3 M
版权声明:本文为CSDN博主「biyezuopin」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 * w: ^3 _1 e }原文链接:https://blog.csdn.net/sheziqiong/article/details/126814418 : S# s2 a# N$ \ W* `. Z& m$ W / V: x+ G$ @! z9 ?4 q! A# b. U ' s4 ]. [% |0 @+ I