获取租房网站信息

思路:
1、麦田网租房信息url=http://bj.maitian.cn/zfall/
2、获取标题描述、房屋面积信息、位置信息,房屋价格及二层url的细节评价
3、设置翻页循环
4、使用xpath解析数据
5、首页和细节页数据存入同一张表里

遇到的问题:
二层页面右键无法点击(简单的反爬)

一、准备工作

  • 创建一个scrapy project:
 scrapy startproject MTZF
  • 创建spider file
 scrapy genspider maitian maitian.com

二、构建框架
(1)items.py / 定义item

import scrapy
class ItemItem(scrapy.Item):
    #声明所有需要的item,与spider里获取的一一对应
    title = scrapy.Field()
    info = scrapy.Field()
    location= scrapy.Field()
    price = scrapy.Field()
    detail = scrapy.Field()

(2) spider.py

import scrapy
from ITEM.items import ItemItem
class MaitianSpider(scrapy.Spider):
    name = 'maitian'
    allowed_domains = ['maitian.cn']
    url = 'http://bj.maitian.cn/zfall/PG{}'
    #从第1页开始爬取
    page = 1
    start_urls = [url.format(page)]
   
   def parse(self, response):
        room_list = response.xpath('//div[@class="list_wrap"]/ul/li[@class="clearfix"]')
        #获取所有的房屋信息列表,得到的是一个可遍历对象
        #设置一个if判断语句,当没有获取到数据时打破翻页循环
        if not roomlist:
        	return None
        #遍历roomlist,取出需要的标签文本数据
        for i in roomlist:
            item = ItemItem()
            #引入item
            #标题
            item['title'] = i.xpath('./div[@class="list_title"]/h1/a/text()').extract_first().strip()
            #scrapy框架中xpath语句得到的对象需要使用extract提取器提取出
            #因为得到的是一个列表,取出仅有的第一个元素,去除多余的空格
            
            #概况
            item['info'] = ','.join(i.xpath('./div[@class="list_title"]/p/span/text()').extract()[:-2]).replace(' ','')
            #观察有几个同级别的span标签,前面几个是想要的概况,最后两个是位置信息,这里我想把他们分开存储,使用了列表的切片
            #取出的text是由空格间隔的词组组成的,使用逗号替代空格
            
            #位置
            item['location'] = ','.join(i.xpath('./div[@class="list_title"]/p/span/text()').extract()[-2:]).strip()
            #同级span标签的后两个是我定义的location数据
            
            #价格
            price = i.xpath('./div[@class="list_title"]/div[@class="the_price"]//span/text()').extract_first()
            unit = i.xpath('./div[@class="list_title"]/div[@class="the_price"]//strong/text()').extract_first()
            item['price'] = price + unit
            #为了格式好看,把价格单位也拼接上

            #获取二层url,爬取评价
            detail_url = 'http://bj.maitian.cn' + i.xpath('./a/@href').extract_first().strip()
            #直接获取的二层url:1、设置了大量空格,需要去除;2、不完整,需要拼接。
            yield scrapy.Request(detail_url,meta={'detail':item},callback=self.parse_info)
            #准备把二层获取的评价与上面获取的信息放入同一个item里,这里item先不返回,通过request传给下一个函数
            #request通过meta以字典形式传递对象,自定义key-value,在下一步使用key值将value取出

    def parse_info(self,response):
        #解析二层代码时遇到的问题:二层网页无法右键点击,一个反爬点
        #解决:访问detail_url,保存html,从本地查看,然后解析
        # with open('bj.html','wb')as f:
        #     f.write(response.body)
        #这一步做一次就可以了,隐藏掉
        
        #承接上一步传来的item
        item = response.meta['detail']
        #获取详情页评价
        item['detail']=response.xpath('.//div[@class="hc_left clearfix"]//label[@class="all_font"]/text()').extract_first()
      	#获取完整想要的数据后,设置自动翻页,拼接第一层url的下一页的地址,继续发送请求、解析数据
      	self.page += 1
      	url = self.url.format(self.page)
        yield item
        yield scrapy.Request(url,callback=self.parse)

(3) middlewares.py

import random
#操控request参数的中间件
#因为下载中间件在后面,所以添加User-Agent使用DownloaderMiddleware
class ItemDownloaderMiddleware(object):
    def __init__(self):
        #复制了一个ug列表
        self. user_agent_list = ["Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
        "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
        "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"]
    #改写重要的一步process_request,传入请求头参数
    def process_request(self, request, spider):
        ug = random.choice(self.user_agent_list)
        #从ug池里随机选出一个user-agent
        #可以自行添加设置if语言防止重复
        request.headers['User-Agent'] = ug
        #将选出的ug传给request
        return None

    def process_response(self, request, response, spider):
        #这一步可以不改写,这里写来验证user-agent是否添加成功
        print('使用了User-Agent:',request.headers['User-Agent'])
        return response

(4)pipelines.py

#数据持久化的管道,将数据保存到非关系型数据库MongoDB中
import pymongo
class ItemPipeline(object):
    def __init__(self):
        client = pymongo.MongoClient()
        #连接数据库,host和port参数使用默认值,这里没有传入
        #host地址:127.0.0.1
        #port端口号:27017
        mydb = client['test']
        #选择数据库test
        self.collection = mydb['maitian']
        #选择表maitian

    def process_item(self, item, spider):
        data = dict(item)
        #将返回的item转为字典格式,MongoDB是以键值对的形式保存数据的
        self.collection.insert(data)
        #python与MongoDB的交互之 插入数据
        return item

(5)一切准备就绪别忘记setting
一般写好一部分代码就开启相应的设置,以防忘记

#设置日志,级别为只看warning
LOG_FILE = 'maitian.log'
LOG_LEVEL = 'WARNING'
#不遵守robot协议
ROBOTSTXT_OBEY = False
#下载延时,太快会被反爬
DOWNLOAD_DELAY = 3
#打开下载中间件,名称要与你设置的一致
DOWNLOADER_MIDDLEWARES = {
   'ITEM.middlewares.ItemDownloaderMiddleware': 543,
}
#打开item管道
ITEM_PIPELINES = {
   'ITEM.pipelines.ItemPipeline': 300,
}

三、运行spider
(1)打开MongoDB服务器,启动客户端

sudo mongod
mongo

(2)运行spider

scrapy crawl maitian

如果需要数据可视化为csv格式:

mongoexport -d test -c maitian -f title,info,location,price,detail --csv -o ./maitian.csv

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值