失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 基于python多线程和Scrapy爬取链家网房价成交信息

基于python多线程和Scrapy爬取链家网房价成交信息

时间:2022-05-16 01:37:11

相关推荐

基于python多线程和Scrapy爬取链家网房价成交信息

文章目录

知识背景Scrapy- spider 爬虫框架SQLite数据库python多线程爬取流程详解爬取房价信息封装数据库类,方便多线程操作数据库插入操作构建爬虫爬取数据基于百度地图获取小区地理坐标完整代码

本次教程以深圳市为例,介绍利用python多线程爬取链家网的房价成交信息。其中涉及的知识包括爬虫框架Scrapy-spider、轻量数据库SQLite等。

知识背景

Scrapy- spider 爬虫框架

简单的说,Scrapy爬虫框架会利用异步机制帮助提高网络爬虫的爬取速度。

最重要的,爬虫记载爬取失败的url,进行重复爬取,直到爬取失败的url列表为空时结束爬取,这显然提高数据的爬取质量。

SQLite数据库

SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它占用资源非常的低,操作简单,适合用于存储爬虫结果数据。

python多线程

多线程就像同时执行多个程序,多线程运行有如下优点:

使用线程可以把占据长时间的程序中的任务放到后台去处理。运行速度更快在一些等待的任务实现上如用户输入、文件读写和网络收发数据等情况下我们可以释放一些珍贵的资源如内存占用等等。

爬取流程详解

爬取房价信息

封装数据库类,方便多线程操作

class SQLiteWraper(object):"""数据库的一个小封装,更好的处理多线程写入"""def __init__(self,path,command='',*args,**kwargs): self.lock = threading.RLock() #锁 self.path = path #数据库连接参数 if command!='':conn=self.get_conn()cu=conn.cursor()cu.execute(command)def get_conn(self): conn = sqlite3.connect(self.path)#,check_same_thread=False) conn.text_factory=strreturn conn def conn_close(self,conn=None): conn.close() def conn_trans(func): def connection(self,*args,**kwargs): self.lock.acquire() conn = self.get_conn() kwargs['conn'] = conn rs = func(self,*args,**kwargs) self.conn_close(conn) self.lock.release() return rs return connection @conn_trans def execute(self,command,method_flag=0,conn=None): cu = conn.cursor()try:if not method_flag:cu.execute(command)else:cu.execute(command[0],command[1])mit()except sqlite3.IntegrityError as e:#print(e)return -1except Exception as e:print(e)return -2return 0@conn_transdef fetchall(self,command="select name from xiaoqu",conn=None):cu=conn.cursor()lists=[]try:cu.execute(command)lists=cu.fetchall()except Exception as e:print(e)passreturn lists

数据库插入操作

利用数组生成数据库插入命令

def gen_xiaoqu_insert_command(info_dict):"""生成小区数据库插入命令"""info_list=[u'小区ID',u'小区名称',u'参考均价',u'大区域',u'小区域',u'建筑年代',u'建筑类型',u'物业费用',u'物业公司',u'开发商',u'楼栋总数',u'房屋总数',u'附近门店']t=[]for il in info_list:if il in info_dict:t.append(info_dict[il])else:t.append('')t=tuple(t)command=(r"insert into xiaoqu values(?,?,?,?,?,?,?,?,?,?,?,?,?)",t)return command

构建爬虫爬取数据

def xiaoqu_spider(db_xq,url_page=u"/xiaoqu/pg1rs%E6%98%8C%E5%B9%B3/"):"""爬取页面链接中的小区信息"""try:res=requests.get(url_page,headers=hds[random.randint(0,len(hds)-1)])plain_text=res.textsoup = BeautifulSoup(plain_text,"html.parser")except (urllib.request.HTTPError, urllib.request.URLError) as e:print(e)exit(-1)except Exception as e:print(e)exit(-1)xiaoqu_list=soup.findAll('li',{'class':'clear xiaoquListItem'})for xq in xiaoqu_list:info_dict={}info_dict.update({u'小区ID':xq.get('data-id')})info_dict.update({u'小区名称':xq.find('div',{'class':'title'}).get_text()})info_dict.update({u'参考均价':xq.find('div',{'class':'totalPrice'}).get_text()})info_dict.update({u'大区域':xq.find('a',{'class':'district'}).get_text()})info_dict.update({u'小区域':xq.find('a',{'class':'bizcircle'}).get_text()})url_detail="/xiaoqu/"+xq.get('data-id')+"/"info=xiaoqu_spider_detail(url_detail)try:info_dict.update({u'建筑年代':info[0]})info_dict.update({u'建筑类型':info[1]})info_dict.update({u'物业费用':info[2]})info_dict.update({u'物业公司':info[3]})info_dict.update({u'开发商':info[4]})info_dict.update({u'楼栋总数':info[5]})info_dict.update({u'房屋总数':info[6]})info_dict.update({u'附近门店':info[7]})except Exception as e:print(url_detail)print(e)command=gen_xiaoqu_insert_command(info_dict)db_xq.execute(command,1)def do_xiaoqu_spider(db_xq,region=u"futianqu"):"""爬取大区域中的所有小区信息"""url=u"/xiaoqu/"+quote(region_pinyin)+"/"try:res=requests.get(url,headers=hds[random.randint(0,len(hds)-1)])plain_text=res.textsoup = BeautifulSoup(plain_text,"html.parser")except (urllib.request.HTTPError, urllib.request.URLError) as e:print(e)returnexcept Exception as e:print(e)returnd=json.loads(soup.find('div',{'class':'page-box house-lst-page-box'}).get('page-data'))total_pages=d['totalPage']threads=[]for i in range(total_pages):url_page=u"/xiaoqu/"+quote(region_pinyin)+"/"+"pg%s/" % (i+1)t=threading.Thread(target=xiaoqu_spider,args=(db_xq,url_page))threads.append(t)for t in threads:t.start()for t in threads:t.join()print(u"爬下了 %s 区全部的小区信息" % region)

基于百度地图获取小区地理坐标

构建函数调用百度地图API,查询poi点位置信息,获取位置标记

def getlocation(name):#调用百度API查询位置bdurl='http://api./place/v2/search?query='output='json'ak='yPNB0qKB6sIVVupOWyKnzoxabwsSuK9M'#输入你刚才申请的密匙region='深圳'tag='房地产'uri=bdurl+name+'&tag='+tag+'&region='+region+'&output='+output+'&ak='+akres=requests.get(uri)s=json.loads(res.text)['results']if s==[]:loc={'lng':'NULL','lat':'NULL'}else:s=json.loads(res.text)['results'][0]loc=s.get('location', 'not exist')if loc=="not exist":loc={'lng':'NULL','lat':'NULL'}return(loc)

完整代码

完整代码请参考个人博客-资源下载。

如果觉得《基于python多线程和Scrapy爬取链家网房价成交信息》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。