Scrapy框架进行数据采集详细实现

摘要

本项目是python课程的课程项目,在简要学习完python和爬虫相关的Scrapy框架后,基于这两者的运用最终完成了对于北京链家网站房页面的信息进行爬取,并将爬取的数据存放于excel之中,使用excel或者wps进行查看。

1 引言

1.1背景

在本学期的python课程中,通过网课粗略的掌握了python的基础知识之后,老师提出通过运用python的模块进行附加的学习,于是我选择了Scrapy框架的学习,由此为基础对于链家网站的信息进行了爬取数据的操作,并将爬取的数据保存。

1.2意义

这个项目提高了我的python编程水平,使得我对于爬虫技术的了解更加深入,粗略掌握了如何使用Scrapy框架进行爬虫操作,懂得了python的附加模块的强大之处,也激发了继续学习编程的兴趣。

1.3相关研究

Scrapy 是用 Python 实现的一个为了爬取网站数据、提取结构性数据而编写的应用框架。Scrapy 常应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。通常我们可以很简单的通过 Scrapy 框架实现一个爬虫,抓取指定网站的内容或图片。之前在基础学习的时候使用的是Python的request模块也能对网站页面的数据进行爬取,但是request属于页面级爬虫,重点在于页面下载,并发考虑不足,性能较差。

2  系统结构

1

该项目是基于Scrapy框架来进行的,因此整体的框架如图1所示。由于Scrapy本身封装了大量的内容操作使得代码编写者可以简化自己的代码量。由于大量的封装,在本次项目中只需要修改SPIDERS模块和ITEM PIPELINES模块。

SPIDERS模块是该项目的python模块。在此放入代码。它解析Downloader返回的响应(Response)产生爬取项(scraped item)。产生额外的爬取请求(Request)

ITEM PIPELINES模块,以流水线的方式处理Spider产生的爬取项。由一组操作顺序组成,类似流水线,每个操作都是一个item Pipeline类型。它的操作包括:清理、检验、和查重爬取的HTML数据、将数据存储到数据库或者其他文件中

Engine(引擎):负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。

Scheduler(调度器):它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。

Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理。

Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件。

Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)

简单地理解就是,有要爬去的任务在Scheduler(调度器)排队等待爬取,然后requests请求Internet,spider在Downloader(下载器)里得到响应,最后通过管道保存到相应位置。

3实现代码

3.1建立工程和Spider模板

scrapy startproject lianjia_bj

建立名为lianjia_bj的工程

scrapy genspider bj lianjia.com

创建一个名为bj的爬虫,搜索的域名范围是lianjia.com

3.2编写Spider

这一部分主要是配置bj.py文件,修改对返回页面的处理,修改对新增URL爬取请求的处理。首先通过对https://bj.lianjia.com/loupan/pg{}网页进行信息提取,获取每个房的房源信息,再通过yield关键字不断提取标签中的信息。这里信息的提取这里使用的是xpath。

通过览器查看网页源代码可以详细去查view-source:https://bj.lianjia.com/loupan/pg1/的代码,然后可以发现li"标签后面紧跟的标签中的属性值就是每个房源的详情信息。使用xpath进行一一提取即可。

代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import scrapy
import time
from lianjia_bj.items import LianjiaBjItem
import random

class BjSpider(scrapy.Spider):
    name = 'bj'
    # allowed_domains = ['bj.lianjia.com']  # 爬取的域,防止跳转到其他链接
    start_urls = ['https://bj.fang.lianjia.com/loupan/pg1']  # 目标URL

    def parse(self, response):
        divs = response.xpath('/html/body/div[3]/ul[2]/li')
        for div in divs:
            item = LianjiaBjItem()
            item['title'] = div.xpath('./div/div[1]/a/text()')[0].extract()
            item['area'] = div.xpath('./div/div[3]/span/text()')[0].extract()
            item['house_leixing'] = div.xpath('./div/div[1]/span[1]/text()')[0].extract()
            item['house_xiaoshou'] = div.xpath('./div/div[1]/span[2]/text()')[0].extract()
            item['house_qu'] = div.xpath('./div/div[2]/span[1]/text()')[0].extract()
            item['house_xiangzhen'] = div.xpath('./div/div[2]/span[2]/text()')[0].extract()
            item['house_dizhi'] = div.xpath('./div/div[2]/a/text()')[0].extract()
            house_huxing1=div.xpath('./div/a/span/text()')
            house_maidian1 = div.xpath('./div/div[5]/span/text()')
            item['money_danjia'] = div.xpath('./div/div[6]/div[1]/span[1]/text()')[0].extract()
            item['money_zongjia'] = div.xpath('./div/div[6]/div[2]/text()')[0].extract()
            if len(house_huxing1)==1:
                item['house_huxing']=house_huxing1[0].extract()
            elif len(house_huxing1)==2:
                item['house_huxing'] = house_huxing1[0].extract()+'/'+house_huxing1[1].extract()
            elif len(house_huxing1) == 3:
                item['house_huxing'] = house_huxing1[0].extract() + '/'+house_huxing1[1].extract()+ '/'+house_huxing1[2].extract()
            elif len(house_huxing1) == 4:
                item['house_huxing'] = house_huxing1[0].extract() + '/'+house_huxing1[1].extract()+ '/'+house_huxing1[2].extract()+ '/'+house_huxing1[3].extract()
            else:
                item['house_huxing'] = house_huxing1[0].extract()
            if len(house_maidian1)==1:
                item['house_maidian']=house_maidian1[0].extract()
            elif len(house_maidian1)==2:
                item['house_maidian'] = house_maidian1[0].extract()+'/'+house_maidian1[1].extract()
            elif len(house_maidian1) == 3:
                item['house_maidian'] = house_maidian1[0].extract() + '/'+house_maidian1[1].extract()+ '/'+house_maidian1[2].extract()
            elif len(house_maidian1) == 4:
                item['house_maidian'] = house_maidian1[0].extract() + '/'+house_maidian1[1].extract()+ '/'+house_maidian1[2].extract()+ '/'+house_maidian1[3].extract()
            else:
                item['house_maidian'] = house_maidian1[0].extract()
            # print(title,area,house_dizhi,house_huxing,house_leixing,house_maidian,house_qu,house_xiangzhen,house_xiaoshou,money_danjia,money_zongjia)
            print(house_huxing1)

            time.sleep(1)
            yield item
        next_url = 'https://bj.fang.lianjia.com/loupan/pg{page}'
        # time.sleep(random(1,3))
        for page in list(range(2, 5)):  # 控制页数
            yield scrapy.Request(next_url.format(page=page),callback=self.parse)  # 回调

3.2编写Pipelines

这一部分主要是配置pipelines.py文件,主要定义对LianjiaBjPipeline_csv

处理类以及通过setting.py文件配置ITEM_PIPLINES选项。这里主要是将爬取的数据放入excel之中,首先建立表头,最后再将爬取的数据进行插入。

代码如下:

from openpyxl import Workbook

class LianjiaBjPipeline_csv(object):  # Excel
    def __init__(self):
        self.wb = Workbook()
        self.ws = self.wb.active
        self.ws.append(['title','area','house_dizhi','house_huxing','house_leixing','house_maidian','house_qu','house_xiangzhen','house_xiaoshou','money_danjia','money_zongjia'])

    def process_item(self, item, spider):
        line = [item['title'],item['area'], item['house_dizhi'], item['house_huxing'],item['house_leixing'],item['house_maidian'], item['house_qu'], item['house_xiangzhen'],item['house_xiaoshou'],item['money_danjia'], item['money_zongjia']]
        self.ws.append(line)
        self.wb.save('bjxinfang.xlsx')
        return item

    def close_spider(self, spider):
        self.wb.save('bjxinfang.xlsx')

这里是setting.py要修改的部分,让框架能够找到我们在piplines中新建的类

ITEM_PIPELINES = {
   'lianjia_bj.pipelines.LianjiaBjPipeline_csv': 100,
}

4 爬虫实现

新建一个scrapy框架的运行程序main.py,这样就可以直接运行,不用在通过cmd命令运行了,方便快捷。代码如下:

from scrapy import cmdline

cmdline.execute ('scrapy crawl bj'.split())

4.1运行爬虫代码

最终结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/400054.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HYDRUS2D/3D模型技术教程

原文链接:HYDRUS2D/3D模型技术教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247612514&idx6&snadf080ddb3394d2f758fc269fa6ce9dc&chksmfa827985cdf5f093af1410f151e11fb6d4b39e7533f401624dc2a2375bdcc74b4b0f6160c58b&token1585…

论文分享 | Fuzz4All: 基于大语言模型的通用模糊测试

大语言模型是当前最受关注的研究热点,基于其生成和理解能力,对现有领域在提升性能和效果上做更多尝试。分享一篇发表于2024年ICSE会议的论文Fuzz4All,它组合多个大语言模型以非常轻量且黑盒的方式,实现了一种跨语言和软件的通用模…

适合所有人的生成式人工智能-学习先导课

欢迎来到为所有人提供的生成式人工智能课(generative AI )。自ChatGPT发布以来,人工智能特别是生成式人工智能引起了许多个人、企业和政府的关注。 这是一项非常颠覆性的技术,已经在改变许多人的学习和工作方式。许多开发者认为生成式AI将使许多人得以赋…

[240812] X-CMD 发布 v0.4.5:更新 gtb、cd、chat、hashdir 模块功能

目录 📃Changelog✨ gtb✨ cd✨ chat✨ hashdir 📃Changelog ✨ gtb 调整了 fzf 预览窗口中书籍文本的显示效果,通过识别文本中的特殊字符、日期、章节标题等信息,为其赋予不同的颜色。 ✨ cd cd 模块新增功能:在找…

RS®ZN-Z8x 开关矩阵

R&SZN-Z8x 开关矩阵 专为多端口矢量网络分析仪测量而设计 R&SZN-Z8x 开关矩阵经过优化设计,专门用于罗德与施瓦茨的矢量网络分析仪。这款经济高效的多方位解决方案可用于多端口设备或多个设备的简单和复杂的测量任务。开关矩阵支持宽频率范围&#xff0…

【论文阅读】YOLOv10: Real-Time End-to-End Object Detection

题目:YOLOv10: Real-Time End-to-End Object Detection 作者:Ao Wang Hui Chen∗ Lihao Liu Kai Chen Zijia Lin Jungong Han Guiguang Ding∗ 清华大学的 motivation: 作者觉得YOLO系列的NMS和某些结构非常的耗时,提出NMS-free和一些列高效…

Qt编译配置OpenCV+opencv_contrib(使用cmake)

本文使用环境 OpenCV: 4.7.0 cmake: 3.30.2 Qt: 5.12.1一、配置环境变量 安装好OpenCV、Qt、cmake后,应配置好一下环境变量: 二、编译OpenCV 打开cmake,编译的源码路径选择opencv文件夹中的sources目录,在opencv文件夹下新建一…

视频汇聚平台智能边缘分析一体机分析平台摄像头异常位移算法识别检测

智能边缘分析一体机在摄像头异常位移检测方面扮演着关键角色,它利用先进的图像处理技术和机器学习算法来实时监测摄像头状态,判断是否发生了非预期的位移。下面是智能边缘分析一体机如何检测摄像头异常位移的详细步骤: 1. 图像帧对比&#x…

SpringBoot中生成条形码的方案实战

​ 博客主页: 南来_北往 系列专栏:Spring Boot实战 ZXing库介绍 ZXing库是一个用于解析和生成多种格式的一维和二维条形码的开源Java库。 ZXing(“zebra crossing”的缩写)库提供了多种条形码格式的支持,包括但不限于QR码、…

Vue3 el-tabs 切换记录选项卡,离开前提示

最近做了一个项目,tabs选项卡 需要在离开当前的选中的项时进行提示并且当取消时定位原位置。 看效果图 当我进行编辑时 触发编辑 但是没有进行保存即提示信息。取消后返回原tabs ,否则确认后进入下个tab。 上代码 tab 一般默认会有一个值,一把是第一…

经典算法题总结:二叉树篇

二叉树解题的思维模式分两类: 是否可以通过遍历一遍二叉树得到答案?如果可以,用一个 traverse 函数配合外部变量来实现,这叫「遍历」的思维模式。是否可以定义一个递归函数,通过子问题(子树)的…

如何平衡冷数据(历史库)的成本与性能?| OceanBase应用实践

随着数据量的迅猛增长,企业和组织在数据库管理方面遭遇的挑战愈发凸显。数据库性能逐渐下滑、存储成本节节攀升,以及数据运维复杂性的增加,这些挑战使得DBA和开发者在数据管理上面临更大的压力。 为了应对这些挑战,对数据生命周期…

Jeecgboot3.6.3的vue3版本的一种flowable动态增加一个用户任务节点的方法(三)后端代码实现

因为这个项目license问题无法开源,更多技术支持与服务请加入我的知识星球。 这部分主要讲后端实现部分 1、增加一个AddTaskVo 类型,提供新增任务需要的数据结构 import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.D…

C#使用Puppeteer

Puppeteer Puppeteer是一个Node.js库,它提供了高级API来通过DevTools协议(Chrome DevTools Protocol https://devtools.chrome.com)控制Chrome或Chromium。 Puppeteer默认情况下无头运行(headless)。 可以配置为运行完整的Chrome或Chromium,运行效果如…

spring02-springbean生命周期(实例化过程)

【README】 本文总结自《spring揭秘》,作者王福强,非常棒的一本书,墙裂推荐; spring容器根据配置元素组装可用系统分2个阶段,包括spring容器启动, springbean实例化阶段; 本文详细分析springbe…

单播---广播---组播

单播 单播(Unicast)是一种网络通信方式,其中数据包被发送到特定的网络接口。与广播(Broadcast)不同,单播只将数据包发送到目标地址指定的单个接收者。 单播的工作原理: 源地址:发…

DATAX自定义KafkaWriter

因为datax目前不支持写入数据到kafka中,因此本文主要介绍如何基于DataX自定义KafkaWriter,用来同步数据到kafka中。本文偏向实战,datax插件开发理论宝典请参考官方文档: https://github.com/alibaba/DataX/blob/master/dataxPlug…

240810-Gradio通过HTML组件打开本地文件+防止网页跳转到about:blank

A. 最终效果 B. 可通过鼠标点击打开文件,但会跳转到about:blank import gradio as gr import subprocessdef open_pptx():pptx_path /Users/liuguokai/Downloads/240528-工业大模型1.pptxtry:subprocess.Popen([open, pptx_path])return "PPTX file opened s…

【npm】如何将开发的vite插件发布到npm

前言 简单说下 npm 是什么: npm 是一个 node 模块管理工具,也是全球最大的共享源。 npm 工具与 nodejs 配套发布,便利开发人员共享代码。npm 主要包括 npm 官方网站、CLI(控制台命令行工具)、和 registry(…

Python酷库之旅-第三方库Pandas(079)

目录 一、用法精讲 326、pandas.Series.str.normalize方法 326-1、语法 326-2、参数 326-3、功能 326-4、返回值 326-5、说明 326-6、用法 326-6-1、数据准备 326-6-2、代码示例 326-6-3、结果输出 327、pandas.Series.str.pad方法 327-1、语法 327-2、参数 327…