Scrapy爬取重庆安居客二手房并存入mysql数据库(上)

本文介绍使用Scrapy框架抓取重庆市一二级区的房产信息,并通过pymysql将数据保存到MySQL数据库的过程。从创建项目、定义Item、开发爬虫到设置Pipeline,详细展示了整个数据抓取和存储的流程。

scrapy是什么

Scrapy是Python开发的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。

官网地址:https://scrapy.org/

官方文档:https://docs.scrapy.org/en/latest/

Github:https://github.com/scrapy/scrapy

准备工作

本项目环境:python3.7.0,mysql8.0.18

windows系统中安装python环境:Windows平台安装Python环境

windows系统中安装mysql数据库:Windows平台安装MySQL数据库

使用pip安装pymysql和scrapy包:

pip install pymysql
pip install scrapy

首先在mysql数据库中创建house_area表来存放市区,然后我们根据每个区来获取对应的数据,创建house_area表的sqlscript如下:

CREATE TABLE `house_area` (
	`id` int UNSIGNED AUTO_INCREMENT,
  `code` varchar(255) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
	`parent_id` int not null DEFAULT 0,
  `parent_code` varchar(255) DEFAULT NULL,
  `display_order` INT NOT NULL DEFAULT 0,
	`created_on` timestamp DEFAULT current_timestamp,
	`updated_on` timestamp DEFAULT current_timestamp on update current_timestamp,
	PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

项目实战

根据官方文档使用scrapy指令快速创建获取市区的scrapy项目:

scrapy startproject hourse_area

创建项目后,目录结构如下:

定义市区的item,如上图所示,我们直接在items.py文件中定义:

class HourseAreaItem(scrapy.Item):
    code = scrapy.Field()
    name = scrapy.Field()
    parent_code = scrapy.Field()
    display_order = scrapy.Field()

开发获取市区的爬虫spider,在spiders目录中创建areaspider.py爬虫文件,主要获取重庆市的一二级区:

import scrapy
import re
from hourse_area.items import HourseAreaItem

class AreaSpider(scrapy.Spider):
    name = 'area'

    allow_domains = ["anjuke.com"]

    start_urls = [
        'https://chongqing.anjuke.com/sale/',
    ]

    def parse(self, response):
        area_lists = response.css('div.div-border.items-list div.items:first-child .elems-l a')

        area_item = HourseAreaItem()
        display_order = 1
        for item in area_lists:
            href = item.css('::attr(href)').extract_first().strip()

            area_item['code'] = href.replace('https://chongqing.anjuke.com/sale/','').replace('/','')
            area_item['name'] = item.css('::text').extract_first().strip()
            area_item['parent_code'] = ''
            area_item['display_order'] = display_order

            display_order += 1

            yield area_item

            yield scrapy.Request(href, callback=self.parse_subarea, meta={'parent_code': area_item['code']})

    def parse_subarea(self, response):
        subarea_lists = response.css('div.div-border.items-list div.items:first-child .elems-l .sub-items a')
        area_item = HourseAreaItem()
        display_order = 1
        for item in subarea_lists:
            href = item.css('::attr(href)').extract_first().strip()

            area_item['code'] = href.replace('https://chongqing.anjuke.com/sale/','').replace('/','')
            area_item['name'] = item.css('::text').extract_first().strip()
            area_item['parent_code'] = response.meta['parent_code']
            area_item['display_order'] = display_order

            display_order += 1

            yield area_item

开发item pipeline保存爬取的重庆市一二级区的数据到mysql数据库中,打开pipelines.py文件开发存储逻辑:

import pymysql

class HourseAreaPipeline(object):
    def __init__(self):
        self.db = pymysql.connect("localhost", "root", "123456", "house", charset="utf8")
        self.cursor = self.db.cursor()

    def __del__(self):
        self.db.close()

    def process_item(self, item, spider):
        select_sql = "select id from house_area where code='%s'" % item['code']
        already_save = self.cursor.execute(select_sql)
        self.db.commit()

        if already_save == 1:
            # 更新
            update_sql = "update house_area set name='%s' where code='%s'" % (item['name'], item['code'])
            self.cursor.execute(update_sql)
            self.db.commit()
        else:
            parent_id = 0

            # 查询父级区域
            if item['parent_code']:
                select_sql = "select id from house_area where code='%s'" % item['parent_code']
                already_save = self.cursor.execute(select_sql)
                house_area = self.cursor.fetchone()
                self.db.commit()

                if already_save == 1:
                    parent_id = house_area[0]

            # 插入
            insert_sql = "insert into house_area(code,name,parent_id,parent_code,display_order)\
                values('%s','%s','%d','%s','%d')"\
                %(item['code'],item['name'],parent_id,item['parent_code'],item['display_order'])
            self.cursor.execute(insert_sql)
            self.db.commit()
        return item

设置项目的settings,打开settings.py文件设置如下两项,其他的保持默认即可:

# 前置代码
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36'
# 后置代码

ITEM_PIPELINES = {
   'hourse_area.pipelines.HourseAreaPipeline': 300,
}

# 后置代码

在项目的根目录下运行scrapy指令开始爬取数据:

scrapy crawl area

如此重庆市的一二级区的数据我们就获取并加工保存在mysql数据库中。下一篇文章介绍如何根据区获取对应的数据。

声明:本项目仅仅供学习使用,使用该项目从事的一切商业行为与博主无关,自行承担责任。

使用Scrapy框架爬取安居客二手房数据的方法如下: ### 爬取步骤 不采用分区域进行爬取,而是直接全部爬取,通过循环下一页完成。先把每一页的所有二手住房详细链接爬取到,请求每一个爬取到的详细链接,解析住房信息。完成所有解析后,请求下一页的链接,再回到第一步循环,直到返回内容为空 [^1]。 ### 代码实现 #### 数据结构定义 在 `items.py` 文件中定义二手房信息的 `item`,不同引用中给出了不同的字段定义示例,可根据需求选择: - 示例一: ```python import scrapy class HourseItem(scrapy.Item): area_code = scrapy.Field() title = scrapy.Field() unit_price = scrapy.Field() total_price = scrapy.Field() code = scrapy.Field() community = scrapy.Field() location = scrapy.Field() build_years = scrapy.Field() floor = scrapy.Field() layout = scrapy.Field() size = scrapy.Field() picture_url = scrapy.Field() url = scrapy.Field() ``` 此示例定义了较为全面的二手房信息字段,包括区域代码、标题、单价、总价等 [^2]。 - 示例二: ```python import scrapy class anjukeItem(scrapy.Item): home_title = scrapy.Field() home_size = scrapy.Field() home_addres = scrapy.Field() home_single_price = scrapy.Field() home_commpy = scrapy.Field() home_orientations = scrapy.Field() home_height = scrapy.Field() home_year = scrapy.Field() home_layout = scrapy.Field() ``` 该示例定义了如房屋标题、大小、地址、单价等相关字段 [^3]。 - 示例三: ```python import scrapy class AnjukeItem(scrapy.Item): price = scrapy.Field() mode = scrapy.Field() area = scrapy.Field() floor = scrapy.Field() age = scrapy.Field() location = scrapy.Field() district = scrapy.Field() ``` 此示例定义了价格、模式、面积等住房信息字段 [^4]。 - 示例四: ```python import scrapy class AnjukespiderItem(scrapy.Item): titile = scrapy.Field() house_type = scrapy.Field() build_time = scrapy.Field() area = scrapy.Field() address = scrapy.Field() price = scrapy.Field() unit_price = scrapy.Field() ``` 该示例定义了标题、房屋类型、建造时间等相关字段 [^5]。 #### 开发 `spider` 开发 `spider` 来实现具体的爬取逻辑,根据上述步骤编写代码,不断循环爬取每一页的链接及详细信息。由于未给出具体的 `spider` 代码示例,以下是一个简单的框架示例: ```python import scrapy from your_project.items import HourseItem # 根据实际选择的 item 类导 class AnjukeSpider(scrapy.Spider): name = "anjuke" start_urls = ['https://example.anjuke.com/ershoufang/'] # 替换为实际的安居客二手房页面 URL def parse(self, response): # 爬取每一页的所有二手住房详细链接 detail_links = response.css('your_selector_for_detail_links').getall() # 替换为实际的 CSS 选择器 for link in detail_links: yield response.follow(link, self.parse_detail) # 请求下一页的链接 next_page = response.css('your_selector_for_next_page').get() # 替换为实际的 CSS 选择器 if next_page is not None: yield response.follow(next_page, self.parse) def parse_detail(self, response): item = HourseItem() # 解析住房信息 item['title'] = response.css('your_selector_for_title').get() # 替换为实际的 CSS 选择器 # 其他字段解析... yield item ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值