Python采集二手房源数据信息 基础版, 多线程版

news2024/12/24 2:35:00

前言

大家早好、午好、晚好吖 ❤ ~

环境使用:

  • Python 3.8

  • Pycharm

模块使用:

  • requests >>> pip install requests 数据请求模块

  • parsel >>> pip install parsel 数据解析模块

  • re

  • csv 内置模块

安装python第三方模块:

  1. win + R 输入 cmd 点击确定, 输入安装命令 pip install 模块名 (pip install requests) 回车

  2. 在pycharm中点击Terminal(终端) 输入安装命令

基本思路流程: <通用版本>

一. 数据来源分析:

  1. 明确需求:

    采集数据内容什么, 采集数据在什么地方有<请求链接可以得到相应的数据>

    • 房源的基本信息
  2. 分析这些房源数据, 请求那个url地址可以得到

    正常操作: 通过开发者工具进行抓包分析 <无论动态网页/静态网页>

    • 打开开发者工具: F12 或者 鼠标右键点击检查选择network <基本上没有数据, 或者数据不全>

    • 刷新网页: 让本网页相关的数据内容重新加载一遍

    • 通过搜索功能, 查询相对应数据包<url地址>

二. 代码实现步骤:

  1. 发送请求, 模拟浏览器对于url地址发送请求

  2. 获取数据, 获取服务器返回响应数据

    开发者工具: response

  3. 解析数据, 提取我们想要的数据内容

    提取: 房源基本信息

  4. 保存数据, 把数据保存表格文件里面

  5. 多页数据采集

代码展示

基础版

导入模块

# 导入数据请求模块 --> 第三方模块 需要安装 pip install requests
import requests
# 导入数据解析模块 --> 第三方模块 需要安装 pip install parsel
import parsel
# 导入csv
import csv
# 导入时间模块
import time
time_1 = time.time()

创建文件 <对象>

f = open('data.csv', mode='a', encoding='utf-8', newline='')
csv_writer = csv.DictWriter(f, fieldnames=[
    '标题'
    '小区',
    '总价',
    '单价',
    '户型',
    '面积',
    '朝向',
    '装修',
    '楼层',
    '建筑日期',
    '建筑类型',
    '详情页',
])

写入表头

csv_writer.writeheader()

“”"

  1. 发送请求, 模拟浏览器对于url地址发送请求
    • 伪装模拟: 请求头 字典数据类型 构建完整键值对
      headers 可以直接在开发者工具里面进行复制

    • <Response [200]> 响应对象
      200 状态码 表示请求成功

“”"

for page in range(1, 101):
    try:
        print(f'==================正在采集第{page}页的数据内容==================')

请求链接

PS:完整源码如有需要的小伙伴可以加下方的群去找管理员免费领取

模拟伪装

        headers = {
            # User-Agent 用户代理, 表示浏览器基本身份信息
            'User-Agent': ' Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
        }

发送请求

        response = requests.get(url, headers)

“”"

  1. 获取数据, 获取服务器返回响应数据

    开发者工具: response

    获取网页源代码

    • response.text 获取响应文本数据, 字符串数据类型 获取html字符串数据内容

    • response.json() 获取响应字典数据 json数据 必须是完整json数据格式

  2. 解析数据, 提取我们想要的数据内容

    提取: 房源基本信息

    解析方法:

    • xpath

    • re正则

    • css

    • json数据处理

    css选择器: 根据标签属性提取数据内容

    1. 看数据在那个标签里面

“”"

        html_data = requests.get(link).text
        select = parsel.Selector(html_data)

把获取下来 html字符串数据 response.text , 转成可解析对象

        selector = parsel.Selector(response.text)

第一次提取, 把包含房源数据信息 标签全部获取下来 获取所有li标签

        lis = selector.css('sellListContent li')

for循环把列表里 元素一个一个提取出来

        for li in lis:

“”"
具体提取li标签里面的内容

  • .info .title a 表示那个标签

  • a::text 表示获取a标签文本内容

  • get 获取标签内容 获取第一个标签内容 返回是字符串

  • getall 获取多个, 返回列表数据

  • .title a::text 表示a标签文本 get() 定位元素

  • attr(href) 获取标签 href 属性

“”"

            源码、解答、资源、学习交流可加企鹅裙:261823976##
            title = li.css('.title a::text').get()  # 标题
            href = li.css('.title a::attr(href)').get()  # 详情页
            totalPrice = li.css('.totalPrice span::text').get()  # 售价
            unitPrice = li.css('.unitPrice span::text').get()  # 单价
            string = select.css('.comments div:nth-child(7) .comment_text::text').get()

join把列表合并字符串

            area = '-'.join(li.css('.info .flood .positionInfo a::text').getall())  # 小区
            houseInfo = li.css('.info .address .houseInfo::text').get()

split 把字符串分割成列表

            houseType = houseInfo.split(' | ')[0]  # 户型
            houseArea = houseInfo.split(' | ')[1]  # 面积
            orientation = houseInfo.split(' | ')[2]  # 朝向
            renovation = houseInfo.split(' | ')[3]  # 装修
            floor = houseInfo.split(' | ')[4]  # 楼层

判断 houseInfo.split(’ | ') 有多少个元素, 如果6个元素 说明没有建造日期

            if len(houseInfo.split(' | ')) == 6:
                date = ''
            else:
                date = houseInfo.split(' | ')[5]
            buildingType = houseInfo.split(' | ')[-1]  # 建筑类型
            dit = {
                '标题': title,
                '小区': area,
                '总价': totalPrice,
                '单价': unitPrice,
                '户型': houseType,
                '面积': houseArea,
                '朝向': orientation,
                '装修': renovation,
                '楼层': floor,
                源码、解答、资源、学习交流可加企鹅裙:261823976##
                '建筑日期': date,
                '建筑类型': buildingType,
                '详情页': href,
            }
            csv_writer.writerow(dit)
            print(string)
    except:
        print('报名系统课程可以添加清风老师微信: pythonmiss')

多线程版

mport requests
import parsel
import re
import csv
# 线程池模块
import concurrent.futures
import time

def get_response(html_url):
    """
    发送请求函数
    :param html_url:
    :return:
    """
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
    }
    response = requests.get(url=html_url, headers=headers)
    return response


def get_content(html_url):
    """
    获取数据函数
    :param html_url:
    :return:
    """
    response = get_response(html_url)
    html_data = get_response(link).text
    selector = parsel.Selector(response.text)
    select = parsel.Selector(html_data)
    lis = selector.css('.sellListContent li')
    content_list = []
    for li in lis:

        title = li.css('.title a::text').get()  # 标题
        area = '-'.join(li.css('.positionInfo a::text').getall())  # 小区
        Price = li.css('.totalPrice span::text').get()  # 总价
        Price_1 = li.css('.unitPrice span::text').get().replace('元/平', '')  # 单价
        houseInfo = li.css('.houseInfo::text').get()  # 信息
        HouseType = houseInfo.split(' | ')[0]  # 户型
        HouseArea = houseInfo.split(' | ')[1].replace('平米', '')  # 面积
        direction = houseInfo.split(' | ')[2].replace(' ', '')  # 朝向
        renovation = houseInfo.split(' | ')[3]  # 装修
        floor_info = houseInfo.split(' | ')[4]
        floor = floor_info[:3]  # 楼层
        floor_num = re.findall('(\d+)层', floor_info)[0]  # 层数
        BuildingType = houseInfo.split(' | ')[-1]
        string = select.css('.comments div:nth-child(7) .comment_text::text').get()
        href = li.css('.title a::attr(href)').get()  # 详情页
        if len(houseInfo.split(' | ')) == 6:
            date = 'None'
        else:
            date = houseInfo.split(' | ')[5].replace('年建', '')  # 日期
        print(string)
        dit = {
        源码、解答、资源、学习交流可加企鹅裙:261823976##
            '标题': title,
            '内容': string,
            '小区': area,
            '总价': Price,
            '单价': Price_1,
            '户型': HouseType,
            '面积': HouseArea,
            '朝向': direction,
            '装修': renovation,
            '楼层': floor,
            '层数': floor_num,
            '建筑日期': date,
            '建筑类型': BuildingType,
            '详情页': href,
        }
        content_list.append(dit)
    return content_list


def main(page):
    """
    主函数
    :param page:
    :return:
    """
    print(f'===============正在采集第{page}页的数据内容===============')

    content_list = get_content(html_url=url)
    for content in content_list:
        csv_writer.writerow(content)

if __name__ == '__main__':
    time_1 = time.time()
    link = 'http:// *******.com/article/149'
    # 创建文件
    f = open('data多线程.csv', mode='a', encoding='utf-8', newline='')
    csv_writer = csv.DictWriter(f, fieldnames=[
        '标题',
        '内容',
        '小区',
        '总价',
        '单价',
        '户型',
        '面积',
        '朝向',
        '装修',
        '楼层',
        '层数',
        '建筑日期',
        '建筑类型',
        '详情页',
    ])
    csv_writer.writeheader()

    # 线程池执行器 max_workers 最大线程数
    exe = concurrent.futures.ThreadPoolExecutor(max_workers=10)
    for page in range(1, 11):
        exe.submit(main, page)
    exe.shutdown()
    time_2 = time.time()
    use_time = int(time_2 - time_1)
    # 总计耗时: 9
    print('总计耗时:', use_time)

尾语 💝

好了,今天的分享就差不多到这里了!

完整代码、更多资源、疑惑解答直接点击下方名片自取即可。

宁外给大家推荐一个好的教程:

【48小时搞定全套教程!你和大佬只有一步之遥【python教程】

有更多建议或问题可以评论区或私信我哦!一起加油努力叭(ง •_•)ง

喜欢就关注一下博主,或点赞收藏评论一下我的文章叭!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基础算法(一)——快速排序

快速排序 介绍 快排是一种复杂度O(nlog(n)nlog(n)nlog(n))的排序算法&#xff0c;在极端情况下会退化为O(n2{n}^2n2)&#xff0c;但是它是一种原地算法&#xff0c;即不需要占据额外空间 原理是先在数列中取一个数x&#xff0c;这个数一般随机选取或是取中间值&#xff0c;然…

四、k8s实战入门

本章节将介绍如何在kubernetes集群中部署一个nginx服务&#xff0c;并且能够对其进行访问。 1 namespace Namespace是kubernetes系统中的一种非常重要资源&#xff0c;它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离。 默认情况下&#xff0c;kubernetes集群…

VuePress搭建文档网站遇到的一些坑点,中文路径,图片显示失败,打包白屏

VuePress搭建文档网站遇到的一些坑点 前言 本篇记录用VuePress搭建文档网站时碰到的一些坑点和解决方案 ★提高阅读体验★ &#x1f449; ♠一级标题 &#x1f448; &#x1f449; ♥二级标题 &#x1f448; &#x1f449; ♥ 三级标题 &#x1f448; &#x1f449; ♥…

HTML与CSS基础(六)—— CSS布局(浮动float)

目标能够使用 结构伪类选择器 在HTML中选择元素 能够说出 标准流 元素的布局特点 能够说出 浮动元素 的特点 能够使用浮动完成 小米模块布局案例 能够说出 清除浮动 的目的&#xff0c;并能够使用 清除浮动的方法一、结构伪类选择器目标&#xff1a;能够使用 结构伪类选择器 在…

MemPrompt: Memory-assisted Prompt Editing with User Feedback

Paper name MemPrompt: Memory-assisted Prompt Editing with User Feedback Paper Reading Note URL: https://arxiv.org/pdf/2201.06009.pdf TL;DR ACL 2022 Workshop CSRR 文章&#xff0c;MemPrompt 将用户对模型预测错误的反馈保存下来&#xff0c;之后遇到类似的问题…

CesiumLab安装、CesiumLab账号注册以及不同授权类型的说明 CesiumLab系列教程

下载软件并安装 官方下载地址&#xff1a;http://cesiumlab.com/#/update 双击 exe 安装。 CesiumLab安装包 CesiumLab安装过程 CesiumLab需要的依赖环境 安装过程会提示 本程序依赖 VC2019 实时运行库&#xff0c;如本机已安装了 VC2019 实时运行库&#xff0c;可以点击【取…

【STM32笔记】HAL库Flash读写配置

【STM32笔记】HAL库Flash读写配置 在keil里面的默认工程配置中 Flash分配地址 程序部分为0x0800 0000到0x0810 0000 总共是0x0010 0000的大小 也就是1048576Byte 1024KB 1MB 而实际上程序部分大小应该要看硬件手册来确定 可以通过配置keil工程中size的大小 来确定程序地址的范…

实验二十七 IPSec配置

实验二十七 IPSec配置实验目的&#xff1a; 某公司由总部和分支机构构成&#xff0c;通过IPsec实验网络安全&#xff0c;保证总部和分支机构的局域 网安全通信。网络拓扑图&#xff1a;IPSec(IP Security)是IETF定义的一组协议&#xff0c;用于增强IP网络的安全性 。 IPsec的功…

【深度学习】李宏毅2021/2022春深度学习课程笔记 - Anomaly Detection(异常侦测)

文章目录一、Problem Formulation二、What is Anomaly&#xff1f;三、Applications四、Binary Classification&#xff1f;五、Categories六、Case 1&#xff1a;With Classifier七、Case 2&#xff1a;Without Labels八、Use Auto-Encoder九、More一、Problem Formulation 假…

Java之反射机制

反射机制 引出反射 我们的猫类 传统的方式 就是new 然后通过对象调用呗 用properties做的话&#xff0c;首先肯定是获取信息 读取配置文件的信息 然后我们需要创建对象是吧 但是这个时候 new classfullpath是不行的&#xff0c;因为我们实际上需要的是 类名 而不是字符串&…

2023年1月7日:fastadmin导出数据为excel格式

需求图&#xff1a; 实现方法&#xff1a; 第一种方法&#xff1a;fastadmin自带导出数据&#xff0c;直接点击下载即可 效果图第二种方法&#xff1a;自定义导出按钮&#xff0c;需要编写方法 效果图&#xff1a; 效果图代码实现 首先&#xff1a;前端按钮代码(可直接拿来用…

【HCIA-openEuler】实验手册—01【openEuler操作系统安装】

文章目录一、实验介绍1、关于本实验2、实验目的3、实验所需材料二、配置虚拟化环境步骤1&#xff1a;硬件准备步骤2&#xff1a;软件准备三、安装openEuler操作系统1、创建虚拟机步骤1&#xff1a;新建虚拟机步骤2&#xff1a;向导选择典型(推荐)步骤3&#xff1a;选择镜像文件…

MonoScene: Monocular 3D Semantic Scene Completion

Paper name MonoScene: Monocular 3D Semantic Scene Completion Paper Reading Note URL: https://arxiv.org/pdf/2112.00726.pdf TL;DR 2022 cvpr 论文&#xff0c;提出一种能在室内与室外场景均可使用的单目 SSC 方案&#xff0c;与特斯拉的 Occupancy Network 非常相似…

【Java基础】day12

一、Redis 的缓存穿透、缓存击穿、缓存雪崩是什么&#xff1f; 缓存穿透 请求不存在【 DB 和 Redis 中都不存在】的数据&#xff0c;导致请求直接打到持久层数据库中&#xff0c;导致数据库负载过高&#xff0c;甚至导致宕机。这样的请求几乎可以导致请求次次到达 DB &#xff…

Cesium中tif转经纬度投影或墨卡托地图瓦片 CesiumLab系列教程

Cesium 目前支持的影像切片规范有两种形式的&#xff1a; 1.经纬度直拉切片方式 &#xff08;GeographicTilingScheme &#xff09;&#xff0c; 2.web 墨卡托切片方式 &#xff08;WebMercatorTilingScheme&#xff09;。 根据常规传统&#xff0c;瓦片大小都是 256&#x…

数字验证学习笔记——SystemVerilog芯片验证22 ——功能覆盖率策略覆盖组

一、功能覆盖率策略 1.1 收集信息而非数据 对于一些设计&#xff0c;你需要关心的是合法的寄存器地址和非法的寄存器地址&#xff0c;可写的寄存器域和非法的寄存器域&#xff0c;而不是具体的寄存器地址数值。一旦关注的地方着眼于感兴趣的状态&#xff0c;而不是具体数值&a…

2022年中职网络安全竞赛SSH弱口令渗透测试解析(详细)

B-7 SSH弱口令渗透测试 任务环境说明: 服务器场景:Server18(关闭链接)服务器场景操作系统:Linux(版本不详)在本地PC渗透测试平台Kali中使用zenmap工具扫描服务器场景Server18-2所在网段(例如:172.16.101.0/24)范围内存活的主机IP地址和指定开放的21、22、23端口。并将…

【NI Multisim 14.0原理图环境设置——标题栏】

目录 序言 一、标题栏 &#x1f34d;1.添加标题块 &#x1f34d; 2.修改标题块 &#xff08;1&#xff09;直接修改 &#xff08;2&#xff09;标题块编辑器 序言 NI Multisim最突出的特点之一就是用户界面友好。它可以使电路设计者方便、快捷地使用虚拟元器件和仪器、仪表…

【C++】命名空间 以及 如何理解using namespace std;

目录 命名空间 1.由来 2.概念 3.使用 方法一 方法二 方法三 4.嵌套使用 命名空间 很多人在学习C的时候&#xff0c;第一个代码想必是如下样子的。和C语言相比&#xff0c;库函数换了&#xff0c;同时多了一个 using namespace std&#xff1b; 但是&#xff0c;你真的了…

Allegro174版本新功能介绍之高阶Contour模式使用

Allegro174版本新功能介绍之高阶Contour模式使用 在Allegro低版本166以及172版本中,有Contour命令,但是只有沿着routekeepin和Connect Line功能,如下图 当升级到了174版本的时候,Allegro支持沿着任意目标走线,甚至是过孔和铜皮,如下图 具体操作介绍如下 以沿着这块铜皮轮…