python爬虫预测_从爬虫到机器学习预测,我是如何一步一步做到的?
作者:xiaoyu
微信公众号:Python数据科学
前情回顾
前一段时间与大家分享了北京二手房房价分析的实战项目,分为分析和建模两篇。文章发出后,得到了大家的肯定和支持,在此表示感谢。
除了数据分析,好多朋友也对爬虫特别感兴趣,想知道爬虫部分是如何实现的。本篇将分享这个项目的爬虫部分,算是数据分析的一个 前传篇。
爬虫前的思考
爬虫部分主要是通过爬取链x和安x客来获取二手房住房信息,因为考虑到不同网站的房源信息可以互补,所以选择了两个网站。
爬取目标是北京二手房,仅针对一个城市而言,数据量并不大。所以直接采用Scrapy来完成爬取工作,然后将数据存储在csv格式的文件中。最终爬取结果是这样的,链x的爬虫爬取了 30000+条数据,安x客的爬虫爬取了 3000+条数据。不得不说链x的房源相对来讲还是比较全的。
scrapy爬取链x
写一个爬虫最开始当然要想清楚需要获取什么样的数据了。本次项目对与二手房相关的数据都比较感兴趣,可以自然的想到,每个房源链接的具体详细信息是最全的。但考虑到爬虫深度影响整体爬虫效率问题,并且房源列表中数据已经能够满足基本的要求,并没有必要对每个详细链接进行深入的爬取,因此最终选择爬取房源列表。以下是房源列表(部分截图)中的房源信息:
确定以上爬取内容后,就开始爬虫部分的工作。首先在item.py文件中定义一个子类,该子类继承了父类scrapy.Item,然后在子类中用scrapy.Field()定义以上信息的字段。如下代码,将所有需要的字段信息都设置好。
import scrapy
class LianjiaSpiderItem(scrapy.Item):
# define the fields for your item here like:
Id = scrapy.Field()
Region = scrapy.Field()
Garden = scrapy.Field()
Layout = scrapy.Field()
Size = scrapy.Field()
Direction = scrapy.Field()
Renovation = scrapy.Field()
Elevator = scrapy.Field()
Floor = scrapy.Field()
Year = scrapy.Field()
Price = scrapy.Field()
District = scrapy.Field()
pass
在spider文件夹下的爬取文件(自定义)中导入所需库,如下代码:
json:json格式的转换;
scrapy:scrapy库;
logging:日志;
BeautifulSoup:使用bs4提取网页信息;
table:settings中自设的一个字典;
LianjiaSpiderItem:字段Field;
# -*- coding:utf-8 -*-
import json
import scrapy
import logging
from bs4 import BeautifulSoup
from lianjia_spider.settings import table
from lianjia_spider.items import LianjiaSpiderItem
下面进入关键部分,即爬虫部分。这部分主要需要自己做的就是如何解析,而对于爬虫是如何爬取的我们不用关心,因为它是框架已经在底层完成调度和爬取的实现,我们只要简单调用即可。
爬虫解析部分,是在继承scrapy.Spider父类的子类LianjiaSpider中完成的。子类中设有三个函数,并通过callback回调逐层实现解析功能,这三个函数是:
start_requests:覆盖父类中原有函数,爬取初始url并存入消息队列中;
page_navigate:解析初始url页面,循环爬取各初始url页面下的所有页码链接;
parse:爬取每个页码下的所有详细房源链接,提取相应的字段信息,并储存至items中;
下面是三个函数的功能描述,以及代码实现。
start_requests
任何爬虫都需要有初始url,然后由初始url继续深入爬取进一步的url,直到爬取到所需数据。由于链家二手房url的特征是,由一个基础url和各大区拼音拼接组成,因此在start_requests函数中定义了base_url的基础url,和需要拼接的北京各大区的拼音列表。
然后由这些拼接的各大区url作为所有的初始url链接,并由scrapy.Request方法对每个链接发出异步请求,代码如下:
class LianjiaSpider(scrapy.Spider):
name = 'lianjia'
base_url = 'https://bj.lianjia.com/ershoufang/'
def start_requests(self):
district = ['dongcheng', 'xicheng', 'chaoyang', 'haidian', 'fengtai', 'shijingshan', 'tongzhou', 'changping',
'daxing', 'yizhuangkaifaqu', 'shunyi', 'fangshan', 'mentougou', 'pinggu', 'huairou',
'miyun', 'yanqing', 'yanjiao', 'xianghe']
for elem in district:
region_url = self.base_url + elem
yield scrapy.Request(url=region_url, callback=self.page_navigate)
page_navigate
对每个大区url发出异步请求后,我们需要对各大区内的所有房源列表url进行进一步的爬取,而为了能够顺利的将全部内容爬取,我们就要解决页码循环的问题。在page_navigate函数中,使用BeautifulSoup解析html,提取页面中的pages数据。
爬取获得的pages数据是json字符串,所以需要使用json.loads将其转换为字典格式,然后得到max_number。最后通过for循环不断发送每个页码url的链接完成异步请求,并使用callback调用进入下一步的函数中,代码如下:
def page_navigate(self, response):
soup = BeautifulSoup(response.body, "html.parser")
try:
pages = soup.find_all("div", class_="house-lst-page-box")[0]
if pages:
dict_number = json.loads(pages["page-data"])
max_number = dict_number['totalPage']
for num in range(1, max_number + 1):
url = response.url + 'pg' + str(num) + '/'
yield scrapy.Request(url=url, callback=self.parse)
except:
logging.info("*******该地区没有二手房信息********")
parse
parse函数中,首先通过BeautifulSoup解析每个页码下的所有房源列表信息,得到house_info_list。链x房源列表中没有所在大区信息,但是房源所在区域对于后续数据分析是很重要的,而仅通过页面解析我们没办法获取。为了获得这个字段该如何实现呢?
我们可以通过response.url来判断,因为url正好是我们开始用所在区域拼接而成的,我们构造url的时候已经包含了大区信息。那么简单的通过辨识url中的大区拼音,就可以解决该问题了。然后使用字典table将对应的中文所在区名映射到Region字段中。
接下来开始对房源列表 house_info_list中的每个房源信息info进行解析。根据链x的页面结构,可以看到,每个info下有三个不同位置的信息组,可通过class_参数进行定位。这三个位置信息分别是house_info,position_info,price_info,每组位置下包含相关字段信息。
house_info:如图包含Garden,Size,Layout,Direction,Renovation,Elevator房屋构造等字段信息;
position_info:如图包含Floor,Year,District等位置年限字段信息;
price_info:如图包含Total_price,price等字段信息;
这里说的位置不同是在前端html页面中的标签位置不同。
具体操作方法参见下面代码:
def parse(self, response):
item = LianjiaSpiderItem()
soup = BeautifulSoup(response.body, "html.parser")
#获取到所有子列表的信息
house_info_list = soup.find_all(name="li", class_="clear")
# 通过url辨认所在区域
url = response.url
url = url.split('/')
item['Region'] = table[url[-3]]
for info in house_info_list:
item['Id'] = info.a['data-housecode']
house_info = info.find_all(name="div", class_="houseInfo")[0]
house_info = house_info.get_text()
house_info = house_info.replace(' ', '')
house_info = house_info.split('/')
# print(house_info)
try:
item['Garden'] = house_info[0]
item['Layout'] = house_info[1]
item['Size'] = house_info[2]
item['Direction'] = house_info[3]
item['Renovation'] = house_info[4]
if len(house_info) > 5:
item['Elevator'] = house_info[5]
else:
item['Elevator'] = ''
except:
print("数据保存错误")
position_info = info.find_all(name='div', class_='positionInfo')[0]
position_info = position_info.get_text()
position_info = position_info.replace(' ', '')
position_info = position_info.split('/')
# print(position_info)
try:
item['Floor'] = position_info[0]
item['Year'] = position_info[1]
item['District'] = position_info[2]
except:
print("数据保存错误")
price_info = info.find_all("div", class_="totalPrice")[0]
item['Price'] = price_info.span.get_text()
yield item
对于链x的爬取,没用xpath的原因是提取一些标签实在不是很方便(只是针对于链x),因此博主采用了beautifulSoup。
scrapy爬取安x客
以下是核心的爬虫部分,与链x爬取部分的思想一致,不同的是使用了xpath进行解析和ItemLoader对item加载储存。
# -*- coding:utf-8 -*-
import scrapy
from scrapy.loader import ItemLoader
from anjuke.items import AnjukeItem
class AnjukeSpider(scrapy.Spider):
name = 'anjuke'
custom_settings = {
'REDIRECT_ENABLED': False
}
start_urls = ['https://beijing.anjuke.com/sale/']
def start_requests(self):
base_url = 'https://beijing.anjuke.com/sale/'
for page in range(1, 51):
url = base_url + 'p' + str(page) + '/'
yield scrapy.Request(url=url, callback=self.parse)
def parse(self, response):
num = len(response.xpath('//*[@id="houselist-mod-new"]/li').extract())
house_info = response.xpath('//*[@id="houselist-mod-new"]')
print(house_info)
for i in range(1, num + 1):
l = ItemLoader(AnjukeItem(), house_info)
l.add_xpath('Layout', '//li[{}]/div[2]/div[2]/span[1]/text()'.format(i))
l.add_xpath('Size', '//li[{}]/div[2]/div[2]/span[2]/text()'.format(i))
l.add_xpath('Floor', '//li[{}]/div[2]/div[2]/span[3]/text()'.format(i))
l.add_xpath('Year', '//li[{}]/div[2]/div[2]/span[4]/text()'.format(i))
l.add_xpath('Garden', '//li[{}]/div[2]/div[3]/span/text()'.format(i))
l.add_xpath('Region', '//li[{}]/div[2]/div[3]/span/text()'.format(i))
l.add_xpath('Price', '//li[{}]/div[3]/span[1]/strong/text()'.format(i))
yield l.load_item()
安x客的反爬比较严重,如果不使用代理ip池,速度过快非常容易挂掉。而链x的反爬相对没那么严格,速度可以很快。
总结
以上是对本项目爬虫部分核心内容的分享,至此这个项目完成了从爬虫到数据分析,再到数据挖掘预测的 "三部曲"完整过程。虽然这个项目比较简单,仍有很多地方需要完善,但是希望通过这个项目能让大家对整个过程有个很好的认识和了解。
关注微信公众号:Python数据科学,发现更多精彩内容。
python爬虫预测_从爬虫到机器学习预测,我是如何一步一步做到的?相关推荐
- bagging和时间序列预测_时间序列的LSTM模型预测——基于Keras
一.问题背景 现实生活中,在一系列时间点上观测数据是司空见惯的活动,在农业.商业.气象军事和医疗等研究领域都包含大量的时间序列数据.时间序列的预测指的是基于序列的历史数据,以及可能对结果产生影 ...
- CNN做时间序列预测_深度学习与时间序列预测
论文下载地址: N-BEATS: Neural basis expansion analysis for interpretable time series forecastingarxiv.org ...
- python多线程爬虫框架_普通爬虫vs多线程爬虫vs框架爬虫,Python爬对比
前言 本文的文字及图片过滤网络,可以学习,交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. 基本开发环境 Python 3.6 皮查姆 目标网页分析 网站就选择发表情这个网站吧 网站是静 ...
- python龙虎榜数据_【爬虫】使用爬虫技术获取盘后龙虎榜
原文来自:MindGo量化社区-[爬虫]使用爬虫技术获取盘后龙虎榜 [导语]本文是"爬虫"系列文章的第一篇.爬虫技术被广泛用于搜索引擎.数据采集等重要领域.搜索引擎提供海量搜索结果 ...
- python爬图片_网络爬虫经验:反爬和反反爬
我想很多人入门python是图片爬虫,就是HTTP请求,保存一下图片,用python实现非常快.网上很多爬虫的教程就讲到这里,实际上很单一,看了跟没看没什么区别,都是找一下网页的规律,然后Beauti ...
- python花瓣图_【爬虫】花瓣图片爬虫,Python图片采集下载源码
#https://huaban.com/search/?q=纹理&category=industrial_design #by 微信:huguo00289 # -*- coding: UTF- ...
- lime 深度学习_用LIME解释机器学习预测并建立信任
lime 深度学习 It's needless to say: machine learning is powerful. 不用说:机器学习功能强大. At the most basic level, ...
- python基于svm实现指数预测_基于SVM的股票预测 Python实现 附Github
SVM 支持向量机 原理就不赘述了,其余的文章有讲过.SVM是一种十分优秀的分类算法,使用SVM也能给股票进行一定程度上的预测. 核心 因为是分类算法,因此不像ARIMA一样预测的是时序.分类就要有东 ...
- java 时间序列预测_基于spark的时间序列预测包Sparkts._的使用
最近研究了一下时间序列预测的使用,网上找了大部分的资源,都是使用python来实现的,使用python来实现虽然能满足大部分的需求,但是python有一点缺点按就是只能使用一台计算资源进行计算,如果数 ...
最新文章
- android7.1.1大小,浅谈Android7.1.1 for 360 N5
- 第一个问题就难倒我了!
- 状态模式 设计模式_设计模式:状态
- 怎样查看Jdk是32位还是64位
- qt利用QSplitter任意拆分窗口
- [Unity脚本运行时更新]C#7.2新特性
- win7的一些小知识
- html标签整合和css框架处理
- python基础学习1-字典的使用
- 重庆自考学历计算机应用基础考试,2017年自考计算机应用基础模拟试题1
- 时间linux防火墙策略,Linux防火墙简介 – iptables配置策略(示例代码)
- 顶隙计算公式_齿轮参数计算公式,这次终于整全了
- pipreqs 命令 ConnectionResetError(10054, ‘An existing connection was forcibly closed by the remote hos
- cad多段线画圆弧方向_【学员分享】CAD多段线用法
- 关于计算机的论文英语2000字,英语论文2000字左右
- vue 动态渲染背景图片
- [全新大碟]周杰倫 - 魔杰座
- 【心理咨询师考试笔记】操作技能(二)——心理评估
- NSFC 申请不中的反思 (内部讨论)
- springBoot 拦截器与过滤器
热门文章
- .net 初学者。学习笔记 [获取varchar32主键的最大ID值]
- msm8953 fm设置频段流程
- xcode与androidstudio 设置自定义主题
- windows之2012缺少api-ms-win-crt**.dll
- 图像处理自学(五):CAMERA驱动软件硬件架构V4L2
- 视频编解码(六):264解码器学习
- 威联通NAS-QTS系统中一些功能的释义
- 解决Element的 InfiniteScroll 无限滚动组件报错
- python json dumps 中文_Python下调用json.dumps中文显示问题解决办法
- linux软连接目标不存在,Linux ln创建软连接之后无法使用,无法whereis