scrapy自动抓取蛋壳公寓最新房源信息并存入sql数据库

利用scrapy抓取蛋壳公寓上的房源信息,以北京市为例,目标url:https://www.dankegongyu.com/room/bj

思路分析

每次更新最新消息,都是在第一页上显示,因此考虑隔一段时间自动抓取第一页上的房源信息,实现抓取最新消息。

利用redis的set数据结构的特征,将每次抓取后的url存到redis中;

每次请求,将请求url与redis中的url对比,若redis中已存在该url,代表没有更新,忽略该次请求;若redis中不存在该url,代表该信息是新信息,抓取并将url存入到redis中。

分析页面源码,发现该网页属于静态网页;首先获取最新页面每条数据的url,请求该url,得到详细页面情况,所有数据均从详情页面获取。

代码实现

明确抓取字段

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy

class DankeItem(scrapy.Item):
    """
    编辑带爬取信息字段
    """
    # 数据来源
    source = scrapy.Field()
    # 抓取时间
    utc_time = scrapy.Field()

    # 房间名称
    room_name = scrapy.Field()
    # 房间租金
    room_money = scrapy.Field()
    # 房间面积
    room_area = scrapy.Field()
    # 房间编号
    room_numb = scrapy.Field()
    # 房间户型
    room_type = scrapy.Field()
    # 租房方式
    rent_type = scrapy.Field()
    # 房间楼层
    room_floor = scrapy.Field()
    # 所在区域
    room_loca = scrapy.Field()
    # 所在楼盘
    estate_name = scrapy.Field()

编写爬虫逻辑

# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from danke.items import DankeItem

class DankeSpider(CrawlSpider):

    # 爬虫名
    name = ‘dkgy3‘

    # 允许抓取的url
    allowed_domains = [‘dankegongyu.com‘]

    custom_settings = {‘DOWNLOAD_DELAY‘: 0.2}

    # 请求开始的url
    start_urls = [‘https://www.dankegongyu.com/room/sz‘]

    # rules属性
    rules = (

        #编写匹配详情页的规则,抓取到详情页的链接后不用跟进
        Rule(LinkExtractor(allow=r‘https://www.dankegongyu.com/room/\d+‘), callback=‘parse_detail‘, follow=False),
    )

    def parse_detail(self, response):
        """
        解析详情页数据
        :param response:
        :return:
        """
        node_list = response.xpath(‘//div[@class="room-detail-right"]‘)
        for node in node_list:
            item = DankeItem()

            # 房间名称
            room_name = node.xpath(‘./div/h1/text()‘)
            item[‘room_name‘] = room_name.extract_first()

            # 房间租金
            room_money = node.xpath(‘./div[@class="room-price"]/div/span‘).xpath(‘string(.)‘).extract_first()

            # 有的房子有首月租金,和普通租金不同,因此匹配方式也不同
            if room_money:
                item[‘room_money‘] = room_money
            else:
                room_money = node.xpath(‘./div[@class="room-price hot"]/div/div[@class="room-price-num"]/text()‘).extract_first()
                item[‘room_money‘] = room_money
                print(room_money)

            # 房间面积
            room_area = node.xpath(‘./*/div[@class="room-detail-box"]/div[1]/label/text()‘).extract_first().split(‘:‘)[-1]
            item[‘room_area‘] = room_area

            # 房间编号
            room_numb = node.xpath(‘./*/div[@class="room-detail-box"]/div[2]/label/text()‘).extract_first().split(‘:‘)[-1]
            item[‘room_numb‘] = room_numb

            # 房间户型
            room_type = node.xpath(‘./*/div[@class="room-detail-box"]/div[3]/label/text()‘).extract_first().split(‘:‘)[-1]
            item[‘room_type‘] = room_type

            # 租房方式
            rent_type = node.xpath(‘./*/div[@class="room-detail-box"]/div[3]/label/b/text()‘).extract_first().split(‘:‘)[
                -1]
            item[‘rent_type‘] = rent_type

            # 所在楼层
            room_floor = node.xpath(‘./div[@class="room-list-box"]/div[2]/div[2]‘).xpath(‘string(.)‘).extract_first().split(‘:‘)[-1]
            item[‘room_floor‘] = room_floor

            # 所在区域
            room_loca = node.xpath(‘./div[@class="room-list-box"]/div[2]/div[3]/label/div/a[1]/text()‘).extract_first()
            item[‘room_loca‘] = room_loca

            # 所在楼盘
            estate_name = node.xpath(‘./div[@class="room-list-box"]/div[2]/div[3]/label/div/a[3]/text()‘).extract_first()
            item[‘estate_name‘] = estate_name

            yield item

编写下载中间件

下载中间件中实现两个逻辑:添加随机请求头和url存入redis中

# -*- coding: utf-8 -*-

# Define here the models for your spider middleware
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/spider-middleware.html
import time
import random
import hashlib
import redis
from scrapy.exceptions import IgnoreRequest
from danke.settings import USER_AGENTS as ua

class DankeSpiderMiddleware(object):
    def process_request(self, request, spider):
        """
        给每一个请求随机分配一个代理
        :param request:
        :param spider:
        :return:
        """
        user_agent = random.choice(ua)
        request.headers[‘User-Agent‘] = user_agent

class DankeRedisMiddleware(object):
    """
    将第一个页面上的每一个url放入redis的set类型中,防止重复爬取
    """
    # 连接redis
    def __init__(self):
        self.redis = redis.StrictRedis(host=‘39.106.116.21‘, port=6379, db=3)

    def process_request(self, request, spider):

        # 将来自详情页的链接存到redis中
        if request.url.endswith(".html"):
            # MD5加密详情页链接
            url_md5 = hashlib.md5(request.url.encode()).hexdigest()

            # 添加到redis,添加成功返回True,否则返回False
            result = self.redis.sadd(‘dk_url‘, url_md5)

            # 添加失败,说明链接已爬取,忽略该请求
            if not result:
                raise IgnoreRequest

数据存储

# -*- coding: utf-8 -*-

from datetime import datetime
import pymysql

class DankeSourcePipeline(object):
    def process_item(self, item, spider):
        item[‘source‘] = spider.name
        item[‘utc_time‘] = str(datetime.utcnow())
        return item

class DankePipeline(object):

    def __init__(self):

        self.conn = pymysql.connect(
            host=‘39.106.116.21‘,
            port=3306,
            database=‘***‘,
            user=‘***‘,
            password=‘****‘,
            charset=‘utf8‘
        )
        # 实例一个游标
        self.cursor = self.conn.cursor()

    def process_item(self, item, spider):

        sql = ("insert into result_latest(标题, 租金, 面积, "
               "编号, 户型, 出租方式, 楼层, "
               "区域, 楼盘, 抓取时间, 数据来源)"
               "values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)")

        item = dict(item)

        data = [
                item[‘room_name‘],
                item[‘room_money‘],
                item[‘room_area‘],
                item[‘room_numb‘],
                item[‘room_type‘],
                item[‘rent_type‘],
                item[‘room_floor‘],
                item[‘room_loca‘],
                item[‘estate_name‘],
                item[‘utc_time‘],
                item[‘source‘],
                ]
        self.cursor.execute(sql, data)
        # 提交数据
        self.conn.commit()

        return item

    def close_spider(self, spider):
        self.cursor.close()
        self.conn.close()

实现自动爬取

import os
import time

while True:
    """
    每隔20*60*60 自动爬取一次,实现自动更新
    """
    os.system("scrapy crawl dkgy3")
    time.sleep(20*60*60)

# from scrapy import cmdline
# cmdline.execute("scrapy crawl dkgy3".split())

完整代码

参见:https://github.com/zInPython/danke

原文地址:https://www.cnblogs.com/pythoner6833/p/9157431.html

时间: 2024-10-11 15:46:45

scrapy自动抓取蛋壳公寓最新房源信息并存入sql数据库的相关文章

python实现爬虫(一)--- Scrapy框架抓取豆瓣书籍信息

Scrapy是一个用python实现都爬虫框架,简单易用,功能强大,只需要在框架的基础上自定义自己的分析规则即可,具体如何新建工程等待都在官方文档上面讲解得非常清楚,官方文档tutorial(http://doc.scrapy.org/en/latest/intro/tutorial.html)请保证下载较新版本的Scrapy(我的是0.24.2,scrapy -v)旧版本会出现一些问题. 下面我使用Scrapy抓取豆瓣上面编程书籍的一些简单信息 一.准备爬取的页面如下,新建一个douban工程

基于python的scrapy爬虫抓取京东商品信息

这是上的第二节爬虫课程的课后作业:抓取京东某类商品的信息,这里我选择了手机品类. 使用scrapy爬虫框架,需要编写和设置的文件主要有phone.py , pipelines.py , items.py , settings.py , 其中主要编写的是前两个文件,最后一个文件主要设置破解反爬方法. phone.py编写程序如下: import scrapy from scrapy.http import Request from jd_phone.items import JdPhoneItem

scrapy递归抓取网页数据

scrapy spider的parse方法可以返回两种值:BaseItem,或者Request.通过Request可以实现递归抓取. 如果要抓取的数据在当前页,可以直接解析返回item(代码中带**注释的行直接改为yield item): 如果要抓取的数据在当前页指向的页面,则返回Request并指定parse_item作为callback: 如果要抓取的数据当前页有一部分,指向的页面有一部分(比如博客或论坛,当前页有标题.摘要和url,详情页面有完整内容)这种情况需要用Request的meta

IIS崩溃时自动抓取Dump

背景:在客户现场,IIS有时会崩溃,开发环境没法重现这个bug,唯有抓取IIS的崩溃是的Dump文件分析. IIS崩溃时自动抓取Dump,需要满足下面几个条件 1.启动 Windows Error Reporting Service 服务 2.移除默认的调试器 如果你的机器装了VS开发工具,会在注册表里写入调试器地址,需要把它删除. 找到注册表删除以下2个项目HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDeb

自动抓取163新闻的Python爬虫源码

Python爬虫的学习,自动抓取163新闻的Python爬虫源码,这是一个用Python语言编写的,自动抓取网易新闻的python爬虫实现方法一文. Python爬虫的抓取思路是:(1)通过分析目标新闻网址 ,分析其中以News.xxx.com 开头的链接(2)获取每一个链接的内容,并做整理合并到事前准备好的.txt 文本中,以便查看各新闻.但是需要注意的是:由于今天的测试对象,网易新闻的格式不是非常统一,所有会有部分漏掉的情况,还能大家见谅.也希望有能力的朋友们帮着改进一下. 自动抓取163新

java抓取12306火车余票信息

最近在弄一个微信的公众帐号,涉及到火车票查询,之前用的网上找到的一个接口,但只能查到火车时刻表,12306又没有提供专门的查票的接口.今天突然想起自己直接去12306上查询,抓取查询返回的数据包,这样就可以得到火车票的信息.这里就随笔记一下获取12306余票的过程. 首先,我用firefox浏览器上12306查询余票.打开firefox的Web控制台,选上网络中的"记录请求和响应主体" 然后输入地址日期信息之后点击网页上的查询按钮,就能在Web控制台下看到网页请求的地址了: 就是图片中

Python 抓取微信公众号账号信息

搜狗微信搜索提供两种类型的关键词搜索,一种是搜索公众号文章内容,另一种是直接搜索微信公众号.通过微信公众号搜索可以获取公众号的基本信息及最近发布的10条文章,今天来抓取一下微信公众号的账号信息( 爬虫 首先通过首页进入,可以按照类别抓取,通过"查看更多"可以找出页面链接规则: import requests as req import re reTypes = r'id="pc_\d*" uigs="(pc_\d*)">([\s\S]*?)

使用python scrapy框架抓取cnblog 的文章内容

scrapy 的文档请移驾到 http://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/install.html 1.准备工作  安装python .Spyder .scrapy 如果想要数据直接入mysql 还需要安装python的 MySQLdb 依赖包 本人mac操作系统 安装MySQLdb的时候出现了些小问题  最后是重装了openssl 才通过的 Spyder 是编写python的ide 2.新建项目  cd /usr/local/var/ww

python网络爬虫之使用scrapy自动爬取多个网页

前面介绍的scrapy爬虫只能爬取单个网页.如果我们想爬取多个网页.比如网上的小说该如何如何操作呢.比如下面的这样的结构.是小说的第一篇.可以点击返回目录还是下一页 对应的网页代码: 我们再看进入后面章节的网页,可以看到增加了上一页 对应的网页代码: 通过对比上面的网页代码可以看到. 上一页,目录,下一页的网页代码都在<div>下的<a>元素的href里面.不同的是第一章只有2个<a>元素,从二章开始就有3个<a>元素.因此我们可以通过<div>