10.2 爬取我爱我家二手房房源数据
10.2.1 我爱我家网站分析
实战-爬取我爱我家二手房房源数据
为了简单,这里仅爬取我爱我家二手房房源的房产标题、总价及房源所属经纪人这 3 项。打开我爱我家二手房房源页面,分析一下页面特点。
图 10-1 展示了房源标题和总价,但是没有经纪人信息,单击进入房源详情页,如图 10-2 所示。
图 10-1 我爱我家二手房房源列表
图 10-2 我爱我家二手房房源详情页
原来经纪人信息在房源详情页。可以从房源列表页面提取标题和总价信息,然后在详情页提取经纪人信息。再来看一下房源列表页如何翻页。单击页面底部的第 2 页,网址变为 https://bj.5i5j.com/ershoufang/n2/。
很显然,URL 最后的数字代表页数,可以随便换成某页验证一下,也可以验证 https://bj.5i5j.com/ershoufang/n1/就是第一页,这样就找到了网址的规律。为了实现翻页,在 Scrapy 中有两种思路。
(1)直接在 start_urls 中构造网址,毕竟已经找到了 URL 构造规律。
(2)从当前爬取页面中提取下一页的 URL,从而实现翻页爬取。
这里使用第一种方法构造网址列表,实现翻页。
10.2.2 我爱我家爬虫项目实现
下面开始编写代码实现我爱我家爬虫。
第一步,生成项目和爬虫文件。在命令行中执行如下命令生成爬虫项目。
>scrapy startproject pachong2
然后进入 pachong2 目录,并使用默认模板生成 spider 爬虫文件。
>cd pachong2 >scrapy genspider woaiwojia bj.5i5j.com
这样就生成了爬虫项目 pachong2,并使用 BasicSpider 模板生成了爬虫文件 woaiwojia.py。
第二步,定义 Item。打开 items.py 定义要爬取的数据。
import scrapy class Pachong2Item(scrapy.Item): apartment = scrapy.Field() total_price = scrapy.Field() agent = scrapy.Field()
这里准备爬取 3 项数据 - apartment、total_price、agent,可以看到定义 item 非常简单。
第三步,编写 spider 文件。打开生成的爬虫文件 woaiwojia.py。
1. 引入 Scrapy 和定义好的 Item
import scrapy from pachong2.items import Pachong2Item
2. 用列表推导式生成 start_urls
直接用列表推导式生成准备爬取的 URL 列表。例如这次要爬取前 10 页的房源数据。
class WoaiwojiaSpider(scrapy.Spider): name='woaiwojia' allowed_domains=['bj.5i5j.com'] start_urls = ['http://bj.5i5j.com/ershoufang/n' + str(x) + '/' for x in range(1,11)]
代码中爬虫类及其中的 name 和 allowed_domains,都是模板自动生成的。
3. 定义房源列表页解析方法
Scrapy 请求 start_urls 得到的 response 作为唯一参数,传给了解析函数 parse。在 parse 函数里面,使用嵌套解析,先解析出每套房源代码段,然后从每一代码段中解析每一套房源的数据并写入到 Item 里。这里需要注意如下 3 点。
(1)为了爬取经纪人信息,要解析出房源详情页 URL,然后使用 scrapy.Request 方法继续请求这个 URL,并使用 callback 参数指定回调函数为 parse_detail。scrapy.Request 这个方法主要用来发起 HTTP 请求、获取响应(response),它的第一个参数是请求的 URL,其他常用参数如下。
method:用于指定请求方法,默认为 GET。
headers:指定请求头部,优先级高于 Scrapy 默认的请求头部。
cookies:指定请求发送的 cookies。
meta:request 的 meta 属性,常用于在解析函数之间传递数据。
callback:指定回调函数。
(2)解析出来的 URL 是不完整的相对路径 URL,应使用 response.urljoin 方法构造绝对路径 URL。response.urljoin 方法能将相对网址转换为绝对网址,它会自动提取出当前页面 URL 的主域名,将相对路径 URL 构造成绝对路径 URL。
(3)parse 函数的 Item 里已经保存了从列表页面爬取到的部分数据,因此需要使用 meta 参数在两个解析函数之间传递 Item 数据。
def parse(self, response): #提取房源列表数据 house_list = response.xpath('//*[@class="pList"]/li') for house in house_list: item = Pachong2Item() #初始化 Item item['apartment'] = house.xpath( 'div[2]/h3/a/text()').extract_first() item['total_price'] = house.xpath( 'div[2]/div[1]/div/p[1]/strong/text()').extract_first() #解析并构造详情页 URL detail_url = response.urljoin(house.xpath( 'div[2]/h3/a/@href').extract_first()) #继续请求详情页 URL,使用 meta 传递已经爬取到的部分数据 #使用 callback 指定回调函数 yield scrapy.Request(detail_url, meta={'item':item}, callback=self.parse_detail)
4. 定义解析房源详情页面的 parse_detail 函数
def parse_detail(self, response): item = response.meta['item'] #接收传递过来的数据 #继续向 Item 添加经纪人信息 item['agent'] = response.xpath( '//*[@class="daikansty"]/ul/li[2] /h3/a/text()').extract_first() yield item #最后返回 Item
这段代码首先使用 response.meta['item']接收传递过来的 Item 数据,然后继续向 Item 添加经纪人信息,最后返回 Item。读者应该能注意到,meta 在传递过来的时候是 request 的一个属性,在接收函数这里,response.meta 实质上是 response.request.meta 的快捷方式。
10.2.3 数据的快捷输出
前面我爱我家爬虫代码已经写好了,我们希望能够将爬取到的数据保存下来,以便后续使用。Scrapy 爬虫框架实现了数据的快捷输出 - Feed 输出,它支持多种序列化格式。Scrapy 快捷输出支持的类型有 json、json lines、csv、xml。
例如,现在要启动我爱我家爬虫,并希望保存为 csv 格式,可以在命令行我爱我家项目根目录下执行如下命令。
>scrapy crawl woaiwojia -o wawj.csv
这里-o 后面是要保存的文件名,因为要保存为 csv 格式,所以文件名的后缀是.csv。如果要保存为 json 格式,可执行如下命令。
>scrapy crawl woaiwojia -o wawj.json
最后提示一点,如果仅仅保存为这几种常见格式,是没有必要配置 pipeline 的,只需使用本节所讲的快捷保存即可,只有保存到数据库时才需配置 pipeline,第 13 章将讲解如何保存数据到数据库。
本节使用我爱我家这样一个实例演示了使用 BasicSpider 模板编写爬虫的技巧和方法,最后还介绍了数据的快捷保存。在爬取小批量数据时,要经常使用数据的快捷保存。下一节将介绍图片下载和翻页的另一种方法。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论