python编程设计高级_Python高级应用程序设计

一、主题式网络爬虫设计方案(15分)

1.主题式网络爬虫名称

链家二手房成交信息(福州地区)

2.主题式网络爬虫爬取的内容与数据特征分析

本爬虫程序爬取链家网福州二手房的成交信息,分别从户型、面积、成交时间、金额去分析,对链家的二手房进行数据的爬取,清洗,数据存储,查找,可视化等操作。

3.主题式网络爬虫设计方案概述(包括实现思路与技术难点)

思路:本文主要使用了multiprocessing模块创建多个进程对象,使用Queue将多个进程联系在一起,也就是线程之间的通信多个对链家的二手房进行数据的爬取,处理,存储等操作。

结构:主从模式:主控制节点、从爬虫节点。

难点:在爬取成交房的列表信息时,发现在请求返回会来得页面并非是静态网页,而是动态的。而且动态网页的抓取相比静态网页来说困难一些,主要涉及的技术是ajax和动态的HTML。简单的网页访问时无法获取完整的数据的,需要对数据加载流程进行分析。本文的解决方式是直接采集浏览器中已经加载好的数据。网上还有一种传统的方式是直接从javascript中采集加载数据。

二、主题页面的结构特征分析(15分)

1.主题页面的结构特征

列表形式

2.Htmls页面解析

使用selenium动态加载的技术,当浏览器将页面全部加载完成时,进行解析

3.节点(标签)查找方法与遍历方法

(必要时画出节点树结构)

使用select css选择器:地址的获取方法,找到所需要的内容-》右键-》copy-》Copy Selector

eg:body > div.content > div.leftContent > ul > li:nth-child(1) > div > div.title > a

然后将返回搜小到ul.listContent

因此标题就可以从里面获取到内容

liList = soup.select('ul.listContent>li')for li inliList:

title= li.select('div > div.title > a')

三、网络爬虫程序设计(60分)

爬虫程序主体要包括以下各部分,要附源代码及较详细注释,并在每部分程序后面提供输出结果的截图。

系统主要核心有两大调度器

页面结构

1、控制调度器

主要负责管理三个进程:一:负责将地址传递给爬虫节点,二:负责读取爬虫节点返回的数据,三:负责将数据提取进程中提交的数据进行数据持久化

#coding:utf-8

frommultiprocessing.managers import BaseManager

import time

import sysfrommultiprocessing import Process, QueuefromDataOutput import DataOutputfromUrlManager import UrlManager'''分布式爬虫'''class NodeManager(object):

def __init__(self):

sys.setrecursionlimit(100000000) # 设置递归分界

self.countPage= 0def start_Manager(self, url_q, result_q):'''创建一个分布式管理器

:param url_q: url队列

:param result_q: 结果队列

:return:'''# 把创建的两个队列注册在网络上,利用register方法,callable参数关联了Queue对象,

# 将Queue对象在网络中暴露

BaseManager.register('get_task_queue', callable=lambda: url_q)

BaseManager.register('get_result_queue', callable=lambda: result_q)

# 绑定端口8001,设置验证口令‘baike’。这个相当于对象的初始化

manager= BaseManager(address=('localhost', 8001), authkey='baike'.encode('utf-8'))

# 返回manager对象

self.countPage= int(input("请爬取您想要爬取的成交的个数(记得要在爬虫节点没开启之前输入):"))returnmanager

def url_manager_proc(self, url_q, conn_q, root_url):

# url管理进程

url_manager=UrlManager()for i in range(1,self.countPage+1):#写死表示要爬取几个列表

url= 'https://fz.lianjia.com/chengjiao/pg'+str(i)+"/"url_manager.add_new_url(url)whileTrue:while(url_manager.has_new_url()):

# 从URL管理器获取新的url

new_url=url_manager.get_new_url()

# 将新的URL发给工作节点

url_q.put(new_url)

print('old_url=', url_manager.old_url_size())

def result_solve_proc(self, result_q, conn_q, store_q):

# 数据提取进程while(True):try:ifnot result_q.empty():

# Queue.get(block=True, timeout=None)

content= result_q.get(block=True, timeout=None)if content['new_urls'] == 'end':

# 结果分析进程接受通知然后结束

print('结果分析进程接受通知然后结束!')

store_q.put('end')returnstore_q.put(content['data']) # 解析出来的数据为dict类型else:

time.sleep(0.1) # 延时休息

except BaseExceptionase:

time.sleep(0.1) # 延时休息

def store_proc(self, store_q):

# 数据存储进程

output=DataOutput()whileTrue:ifnot store_q.empty():

data= store_q.get()if data == 'end':

print('存储进程接受通知然后结束!')

output.add_mysql()

df=output.get_house()

print(">>>>>>>>>>>>>>>>>>>>二手成交房基本信息表")

print(df[['id', 'addr', 'house_class', 'size', 'closing_time', 'price']])

output.show(df)returnoutput.store_data(data)else:

time.sleep(0.1)

passif __name__=='__main__':

#初始化4个队列

url_q=Queue()

result_q=Queue()

store_q=Queue()

# 数据提取进程存储url的队列

conn_q=Queue()

# 数据提取进程存储data的队列

# 创建分布式管理器

node=NodeManager()

manager=node.start_Manager(url_q,result_q)

#创建URL管理进程、 数据提取进程和数据存储进程

root_url= 'https://fz.lianjia.com/chengjiao/'url_manager_proc= Process(target=node.url_manager_proc, args=(url_q,conn_q,root_url,))

result_solve_proc= Process(target=node.result_solve_proc, args=(result_q,conn_q,store_q,))

store_proc= Process(target=node.store_proc, args=(store_q,))

#启动3个进程和分布式管理器

url_manager_proc.start()

result_solve_proc.start()

store_proc.start()

manager.get_server().serve_forever()#永远服务

刚开始提示输入,要爬取几页:

2、爬虫调度器

爬虫节点主要是包括两个功能,下载html内容和解析html内容并跟控制节点进行交互

1 #coding:utf-8

2 from multiprocessing.managers importBaseManager3 importtime4 importsys5

6 from HtmlDownloader importHtmlDownloader7 from HtmlParser importHtmlParser8

9

10 classSpiderWork(object):11 def __init__(self):12 sys.setrecursionlimit(1000000) #例如这里设置为一百万

13 #初始化分布式进程中的工作节点的连接工作

14 #实现第一步:使用BaseManager注册获取Queue的方法名称

15 BaseManager.register('get_task_queue')16 BaseManager.register('get_result_queue')17 #实现第二步:连接到服务器:

18 server_addr = '127.0.0.1'

19 print(('Connect to server %s...' %server_addr))20 #端口和验证口令注意保持与服务进程设置的完全一致:

21 self.m = BaseManager(address=(server_addr, 8001), authkey='baike'.encode('utf-8'))22 #从网络连接:

23 self.m.connect()24 #实现第三步:获取Queue的对象:

25 self.task =self.m.get_task_queue()26 self.result =self.m.get_result_queue()27

28 #初始化网页下载器和解析器

29 self.downloader =HtmlDownloader()30 self.parser =HtmlParser()31 print('init finish')32

33 defcrawl(self):34 while(True):35 try:36 if notself.task.empty():37 url =self.task.get()38 print('爬虫节点正在解析:%s'%url.encode('utf-8'))39 print(self.task.qsize())40 content =self.downloader.download(url)41 new_urls,datas =self.parser.parser(url,content)42 for data indatas:43 print(data)44 self.result.put({"new_urls":new_urls,"data":data})45 if self.task.qsize() <=0:46 print('爬虫节点通知控制节点停止工作...')47 #接着通知其它节点停止工作

48 self.result.put({'new_urls':'end','data':'end'})49 return

50 exceptEOFError as e:51 print("连接工作节点失败")52

53 return

54 exceptException as e:55 print(e)56 print('Crawl faild')57

58

59

60

61 if __name__=="__main__":62 spider =SpiderWork()63 spider.crawl()

数据库的主要数据库表的实体属性

1.数据爬取与采集

爬虫节点下的下载,将获取到的url进行动态的解析,当页面加载完成却,code为200

1 #coding:utf-8

2 importrequests3 importchardet4 from selenium importwebdriver5

6 classHtmlDownloader(object):7 def __init__(self):8 opt =webdriver.chrome.options.Options()9 opt.set_headless()10 self.browser = webdriver.Chrome(chrome_options=opt)11

12 defdownload(self,url):13 if url isNone:14 returnNone15 self.browser.get(url)16 #self.browser.switch_to.frame('g_iframe')

17 html =self.browser.page_source18 return html

2.对数据进行清洗和处理

将列表内容的信息解析成有用的特征值

1 #coding:utf-8

2 importre3 importurllib.parse4 from bs4 importBeautifulSoup5

6

7 classHtmlParser(object):8

9 defparser(self,page_url,html_cont):10 '''

11 用于解析网页内容抽取URL和数据12 :param page_url: 下载页面的URL13 :param html_cont: 下载的网页内容14 :return:返回URL和数据15 '''

16 if page_url is None or html_cont isNone:17 return

18 soup = BeautifulSoup(html_cont,'html.parser')19 new_urls =self._get_new_urls(page_url,soup)20 new_datas =self._get_new_data(page_url,soup)21 returnnew_urls,new_datas22

23

24 def_get_new_urls(self,page_url,soup):25 new_urls =set()26 returnnew_urls27

28 def_get_new_data(self,page_url,soup):29 '''

30 抽取有效数据31 :param page_url:下载页面的URL32 :param soup:33 :return:返回有效数据34 '''

35 dataList =[]36 liList = soup.select('ul.listContent>li')37 for li inliList:38 title = li.select('div > div.title > a')39 result = re.split(r'[\s]+', title[0].string) #使用正则表达式分割

40 addr =result[0]41 house_class = result[1]42 size = result[2]43 #定位 eg:高楼层(共26层) 塔楼

44 #position = str(li.select('div > div.flood > div.positionInfo')[0].string)

45 closing_time = str(li.select('div > div.address > div.dealDate')[0].string) #加str() 防止报:RecursionError: maximum recursion depth exceeded while pickling an object

46 price = int(re.compile(r'[\d]+').findall(li.select('div > div.address > div.totalPrice > span')[0].string)[0])47 data = {'addr':addr,'house_class':house_class,'size':size,'closing_time':closing_time,'price':price}48 dataList.append(data)49 return dataList

清洗部分:

解析的数据内容:

4.数据分析与可视化

(例如:数据柱形图、直方图、散点图、盒图、分布图、数据回归分析等)

1 #coding:utf-8

2 importcodecs3 importtime4 importpymysql as ps5 importpandas as pd6 importmatplotlib.pyplot as plt7 importnumpy as np8

9 classDataOutput(object):10 def __init__(self):11 self.datas =[]12 self.host = "localhost"

13 self.user = "root"

14 self.password = ""

15 self.database = "lianjia"

16 self.charset = "utf-8"

17 self.db =None18 self.curs =None19

20 defstore_data(self, data):21 if data isNone:22 return

23 self.datas.append(data)24 defadd_mysql(self):25 returnself.output_mysql()26 defoutput_mysql(self):27 sql = "insert into chenjiao (addr, house_class, size, closing_time,price) values(%s,%s,%s,%s,%s)"

28 num =029 self.open()30 for data inself.datas:31 try:32 params = (data['addr'], data['house_class'], data['size'], data['closing_time'],data['price'])33 num = num +self.curs.execute(sql, params)34 self.db.commit()35 except:36 print('存取%s失败'%data)37 self.db.rollback()38 self.close()39 returnnum40 defopen(self):41 self.db = ps.connect(host=self.host, user=self.user, password=self.password, database=self.database)42 self.curs =self.db.cursor()43 defclose(self):44 self.curs.close()45 self.db.close()46

47 defget_house(self):48 self.open()49 try:50 sql = sql = "select * from chenjiao order by id asc"

51 datas = pd.read_sql(sql=sql, con=self.db)52 returndatas53 self.close()54 except:55 print("显示失败!")56 self.close()57 defshow(self,data):58 print(data.describe())59 dataHouseClass = data['house_class']60 dataDict ={}61 for value indataHouseClass.values:62 if value indataDict.keys():63 dataDict[value] = dataDict[value]+1

64 else:65 dataDict[value] = 1

66 plt.figure()67 plt.rcParams['font.sans-serif'] = ['SimHei']68 zone1 = plt.subplot(1,2,1)69 plt.bar(['平均值','最小值','最大值','25%','50%','75%'],[data.describe().loc['mean','price'],data.describe().loc['min','price'],data.describe().loc['max','price'],data.describe().loc['25%','price'],data.describe().loc['50%','price'],data.describe().loc['75%','price']])70 plt.ylabel('价格')71 plt.title('基本信息表')72 zone2 = plt.subplot(1, 2, 2)73 plt.pie(dataDict.values(),labels=dataDict.keys(),autopct='%1.1f%%')74 plt.title('比例图')75 plt.show()

5.数据持久化

同上的数据可视化同一个文件内的不同函数中,主要核心代码如下:

defoutput_mysql(self):

sql= "insert into chenjiao (addr, house_class, size, closing_time,price) values(%s,%s,%s,%s,%s)"num=0

self.open()for data inself.datas:try:

params= (data['addr'], data['house_class'], data['size'], data['closing_time'],data['price'])

num= num +self.curs.execute(sql, params)

self.db.commit()except:print('存取%s失败'%data)

self.db.rollback()

self.close()return num

四、结论(10分)

1.经过对主题数据的分析与可视化,可以得到哪些结论?

在这些链家二手房福州地区的成交记录中,单套成交金额最高达到400多万,最低仅几十万,其中75%的住户单套成交金额在200万到300万之间。

最受欢迎的户型是3室2厅,高达46.7%,其次是四室二厅16.7%和二室二厅13.3%。

2.对本次程序设计任务完成的情况做一个简单的小结。

本次的爬虫对我来说是一个挑战,从生疏到有一定的了解,这是一个进步的过程,同时也增加了编程学识的能力!

要学的东西还很多,希望自己保持求学的态度,继续前行!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python高级程序设计是指在Python编程语言中使用更高级的技术和概念来解决复杂的问题和开发更强大的应用程序。以下是Python高级程序设计的一些主题和技术: 1. 面向对象编程(OOP):Python是一种面向对象的编程语言,它支持类、对象、继承、多态等OOP概念。通过使用类和对象,可以将代码组织成更可维护和可重用的模块。 2. 异常处理:Python提供了异常处理机制,可以捕获和处理程序运行时可能出现的错误。通过使用try-except语句,可以优雅地处理异常情况,提高程序的健壮性。 3. 迭代器和生成器:迭代器和生成器是Python中强大的工具,用于处理大量数据或无限序列。迭代器允许按需逐个访问数据,而生成器则可以动态生成数据,节省内存和提高性能。 4. 装饰器:装饰器是一种特殊的函数,用于修改其他函数的行为或功能。通过使用装饰器,可以在不修改原始函数代码的情况下添加额外的功能,如日志记录、性能分析等。 5. 并发和并行编程:Python提供了多线程和多进程编程的支持,可以实现并发和并行执行任务。通过使用线程和进程,可以提高程序的响应性和处理能力。 6. 元编程:元编程是指在运行时操作程序的结构和行为。Python提供了元类和反射等机制,可以动态地创建类、修改类的属性和方法,以及在运行时获取对象的信息。 7. 函数式编程:函数式编程是一种编程范式,强调使用纯函数和不可变数据来编写程序。Python支持函数作为一等公民,可以将函数作为参数传递给其他函数,以及返回函数作为结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值