最近在学习scrapy爬虫,正好最近成都房价涨的厉害,于是想着去网上抓抓成都最近的房价情况,顺便了解一下,毕竟咱是成都人,得看看这成都的房子我以后买的起不~
话不多说,进入正题:
任务
抓取链家网(成都)的所有新房以及二手房价格、位置相关信息。
实验流程
1.确定抓取目标.
2.制定抓取规则.
3.'编写/调试'抓取规则.
4.获得抓取数据
1.确定抓取目标
1.1新房抓取目标
我们看到在成都楼盘列表页面,有楼盘名字、均价(每平方)和所属行政区,非常好,这正是我们想要抓取的内容!
于是确定目标:
抓取成都新房的所有楼盘名称、均价信息、所属行政区和URL信息。
1.2二手房抓取规则
我们来到二手房的列表页面,并且点击进入二手房详情页面,发现网站所展示的内容就比新房的内容的多得多了,这样我们也能抓取更多的数据了!在这里,我决定在二手房页面抓取二手房地址、总价、每平米价、面积、所属行政区域和URL信息。
2.制定抓取规则
2.1新房抓取规则
由于新房的信息直接在新房列表网页上就能直接抓取,所以只需要在新房列表网页分析html结构找到我们想要的数据即可。
对于均价来说,我们所需要的信息在 **//div[@class='average']/span/text() **
对于楼盘名称来说,我们所需要的信息在 //div[@class='col-1']/h2/a/text()
当然了,我们所需要的URL也在 //div[@class='col-1']/h2/a/@href
对于行政区来说,所需要的信息在 //div[@class='where']/span/text(),当然了,我们还得使用正则将所属行政区匹配出来
如何抓取所有的新房信息呢?我们利用下一页来循环
2.2二手房抓取规则
抓取规则和新房抓取规则大同小异,不过这里有一点小小的区别是我们需要利用二手房列表页面抓取到的URL,进入二手房详情页抓取信息,不过这一点我们将在代码实现中讲到,在这儿先按住不表,还是继续分析html结构。
小区名称在 div[@class='communityName']/a[@class='info']/text()
房总价在 div[@class='price ']/span[@class='total']/text()
每平方价在 div[@class='price ']/div[@class='text']/div/span/text() ,当然这里我们还是得用正则把两个引号给弄掉~
所属行政区在 div[@class='areaName']/span[@class='info']/a/text()的第一个text
面积在 div[@class='houseInfo']/div[@class='area']/div[@class='mainInfo']/text()
当然了,对于循环获得所有信息来说,我们还是用网站的“下一页”来做。
3.'编写/调试'抓取规则
为了让调试爬虫的粒度尽量的小,我将编写和调试模块糅合在一起进行.
3.1'编写/调试'新房抓取规则
首先我们得定义一个item:
class NewHoseItem(scrapy.Item):
name = scrapy.Field()
average = scrapy.Field()
district = scrapy.Field()
URL = scrapy.Field()
然后我们尝试抓取一个新房列表页面下的所需数据吧~
import scrapy
from fangjia.items import NewHouseItem
class NewsHouseSpider(scrapy.Spider):
name = "new"
start_urls = [
"http://cd.fang.lianjia.com/loupan/pg1/",
]
def parse(self, response):
for href in response.xpath("//div[@class='info-panel']"):
item = NewHouseItem()
item['name'] = href.xpath("div[@class='col-1']/h2/a/text()").extract_first()
item['average'] = href.xpath("div[@class='col-2']/div[@class='price']/div[@class='average']/span/text()").extract_first()
item['district'] = href.xpath("div[@class='col-1']/div[@class='where']/span/text()").extract_first().split('-')[0]
item['URL'] = response.urljoin(href.xpath("div[@class='col-1']/h2/a/@href").extract_first())
yield item
测试通过!
现在我们再编写一下循环的规则就ok了!
由于我们需要获取到totalpage的值和curpage的值,所以我们得对获取到的字符串稍微的处理一下,这里我们用到的是split()
next_page = response.xpath("//div[@class='page-box house-lst-page-box']/@page-data").extract_first().split(',')[1].split(':')[1]
next_page = int(next_page[0])+1
total_page = int(response.xpath("//div[@class='page-box house-lst-page-box']/@page-data").extract_first().split(',')[0].split(':')[1])
if next_page <= total_page:
next_urls = 'pg%s/' % next_page
next_urls = response.urljoin(next_urls)
yield scrapy.Request(next_urls,callback = self.parse)
组装到我们的原函数里面
import scrapy
from fangjia.items import NewHouseItem
class NewsHouseSpider(scrapy.Spider):
name = "new"
start_urls = [
"http://cd.fang.lianjia.com/loupan/",
]
def parse(self, response):
for href in response.xpath("//div[@class='info-panel']"):
item = NewHouseItem()
item['name'] = href.xpath("div[@class='col-1']/h2/a/text()").extract_first()
item['average'] = href.xpath("div[@class='col-2']/div[@class='price']/div[@class='average']/span/text()").extract_first()
item['district'] = href.xpath("div[@class='col-1']/div[@class='where']/span/text()").extract_first().split('-')[0]
item['URL'] = href.xpath("div[@class='col-1']/h2/a/@href").extract_first()
yield item
next_page = response.xpath("//div[@class='page-box house-lst-page-box']/@page-data").extract_first().split(',')[1].split(':')[1]
next_page = int(next_page[0])+1
total_page = int(response.xpath("//div[@class='page-box house-lst-page-box']/@page-data").extract_first().split(',')[0].split(':')[1])
if next_page <= total_page:
next_urls = 'pg%s/' % next_page
next_urls = response.urljoin(next_urls)
yield scrapy.Request(next_urls,callback = self.parse)
测试,成功!
3.2'编写/调试'二手房抓取规则
二手房抓取规则和新房差不多,所以写简单一点,其中主要说明一点是利用二手房列表页面抓取到的URL,进入二手房详情页抓取信息。
先定义item:
class OldHouseItem(scrapy.Item):
name = scrapy.Field()
total = scrapy.Field()
average = scrapy.Field()
size = scrapy.Field()
district = scrapy.Field()
URL = scrapy.Field()
当然了,我们还是先写出一个二手房列表页面的抓取规则,其中,得利用抓取到的URL再进入二手房详情页进行抓取。
编写爬虫:
import scrapy
from fangjia.items import OldHouseItem
class OldsHouseSpider(scrapy.Spider):
name = "old"
start_urls = [
"http://cd.lianjia.com/ershoufang/",
]
def parse(self, response):
for href in response.xpath("//ul[@class='sellListContent']/li"):
URL = href.xpath("div[@class='info clear']/div[@class='title']/a/@href").extract()
yield scrapy.Request(URL, callback=self.parse_dir_contents)
def parse_dir_contents(self, response):
item = OldHouseItem()
item['name'] = response.xpath("div[@class='communityName']/a[@class='info']/text()").extract_first()
item['total'] = response.xpath("div[@class='price ']/span[@class='total']/text()").extract_first()
item['average'] = response.xpath("div[@class='price ']/div[@class='text']/div/span/text()").extract_first()
item['size'] = response.xpath("div[@class='houseInfo']/div[@class='area']/div[@class='mainInfo']/text()").extract_first()
item['district'] = response.xpath("div[@class='areaName']/span[@class='info']/a/text()").extract_first()
item['URL'] = response
yield item
发现有重定向:
一看,是robot的原因,于是我们进入 http://cd.lianjia.com/robots.txt 一探究竟
在robots.txt最下面看到
User-agent:*
Disallow:/
原来我们的scrapy被屏蔽了!
当然,我们还有办法,不过笔者得去吃午饭了!晚上再回来研究研究~