python代码运行速度有点慢 ? 教你使用多线程速度飞升

news2024/11/19 18:40:15

前言

嗨喽,大家好呀~这里是爱看美女的茜茜呐

又到了学Python时刻~

在我们爬取数据的时候,有时候它运行速度会非常慢

那么怎么解决呢?

这里给大家带来一个多线程的方法

我们用采集二手车来举例

环境使用:

  • Python 3.8

  • Pycharm

模块使用:

  • requests 数据请求模块

  • parsel 数据解析模块

  • re

  • csv 内置模块

一. 代码实现步骤:

  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}页的数据内容==================')

请求链接

( 因不可抗原因,不能出现网址,会发不出去,用图片代替了,大家照着敲一下

或者点击此处跳转跳转文末名片加入裙聊,找管理员小姐姐领取呀~ )

模拟伪装

        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:
            源码、解答、资源、学习交流可加企鹅裙: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)

尾语

感谢你观看我的文章呐~本次航班到这里就结束啦 🛬

希望本篇文章有对你带来帮助 🎉,有学习到一点知识~

躲起来的星星🍥也在努力发光,你也要努力加油(让我们一起努力叭)。

最后,宣传一下呀~👇👇👇更多源码、资料、素材、解答、交流皆点击下方名片获取呀👇👇👇

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

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

相关文章

JVM类加载机制-让你明明白白的了解类的执行流程

一、类加载运行过程1.1 类加载到jvm的流程当我们使用java命令运行某个类的main函数启动程序时&#xff0c;首先需要通过类加载器把主类加载到jvm里。1.2 loadClass的类加载过程其中loadClass的类加载过程有如下几步&#xff1a;加载 >> 验证 >> 准备 >> 解析…

关于Visual Studio C++项目属性设置的说明

链接器—常规—输出文件 这里的输出文件指的是最终生成的exe文件 C/C–常规—附加包含目录 这里指的是需要include的一些头文件所在的 目录&#xff0c;可以提前在项目文件中建立好include文件&#xff0c;然后在这里设置&#xff0c;以后将一些自定义的include头文件放在这个…

Python之父强烈推荐,爬虫入门经典《python3网络爬虫开发实战》

实操性很强的一本工具书&#xff0c;由浅入深&#xff0c;深入浅出。前面从环境配置到爬虫原理、基本库和解析库的使用再到数据存储&#xff0c;一步步把基础打好&#xff0c;然后再分门别类介绍了Ajax、动态页、验证码、App的爬取、识别等&#xff0c;还讲解了代理使用、模拟登…

【Java】Spring中Aware接口的作用

Spring的几个aware接口的用法 ApplicationContextAware public interface ApplicationContextAware extends Aware {void setApplicationContext(ApplicationContext applicationContext) throws BeansException; }该接口仅有一个方法&#xff0c;用于设置Spring容器上下文。…

浅谈Springboot自动配置

目录 1.自动配置原理 2.自动配置案例 3.总结 1.自动配置原理 在一个Springboot程序中&#xff0c;我们只需要在main程序中使用springBootApplication注解即可标记为一个一个Springboot程序&#xff0c;然后使用 SpringApplication.run(TestMain.class,args) 代码即可创建…

多把锁,死锁,活锁,饥饿

目录 多把锁 多把锁的优缺点 活跃性 死锁 手写死锁 死锁的四个必要条件 定位死锁 jconsole运行命令 jps 定位进程 id&#xff0c;再用 jstack 定位死锁 死锁的三种场景 一个线程一把锁 两个线程两把锁 多个线程多把锁 解决死锁 活锁 饥饿 多把锁 现在有一个场…

Kali Linux ping扫描命令

1.命令介绍 kali的ping命令和centos linux的评命令许多参数都差不多&#xff0c;可以看一下我之前写的linuxping命令https://blog.csdn.net/qq_44652591/article/details/128439494 ping扫描是ping整个网络IP地址或单个IP&#xff0c;以查明它们是否活跃和响应的过程。ping也是…

用Kettle调用Restful API 接口

1 概述 kettle 中文名称叫水壶&#xff0c;是纯 java 开发&#xff0c;开源的 ETL工具&#xff0c;用于数据库间的数据迁移 。可以在 Linux、windows、unix 中运行。有图形界面&#xff0c;也有命令脚本还可以二次开发。当然它也可以用来调用Restful API 来采集数据&#xff0c…

【安全硬件】Chap.6 IC和半导体产业的全球化;芯片生产猜疑链与SoC设计流程;可能会存在的安全威胁: 硬件木马、IP盗版、逆向工程、侧信道攻击、伪造

【安全硬件】Chap.6 IC和半导体产业的全球化&#xff1b;芯片生产猜疑链与SoC设计流程&#xff1b;可能会存在的安全威胁: 硬件木马、IP盗版、逆向工程、侧信道攻击、伪造背景1. IC和半导体产业的全球化2. 芯片生产猜疑链——Untrusted IC Supply Chain Threats可能会存在的安全…

我只是把握好了这3点,1个月后成功拿下大厂offer!

目录 一、写在前面二、技术广度的快速准备三、技术深度的快速准备四、基础功底的快速准备五、下篇预告 一、写在前面 春节过后&#xff0c;即将迎来的是一年一度的金三银四跳槽季。 假如你准备在金三银四跳槽的话&#xff0c;那么作为一个Java工程师&#xff0c;应该如何利…

【Shell】mksh运行分析

mksh运行分析 Shell shell&#xff0c;壳子&#xff0c;即操作系统的壳子。这层壳子套在操作系统上&#xff0c;为用户提供与操作系统的交互手段。 操作系统的交互方式一般有&#xff0c;图形化交互(GUI)和命令行交付(CLI,command-line interface)。 套在操作系统上的壳子 …

虚拟机栈

虚拟机栈简介虚拟机栈的出现背景内存中的栈与堆虚拟机栈基本内容虚拟机栈的特点虚拟机栈的异常设置栈内存大小栈的存储单位栈中存储什么&#xff1f;栈运行原理栈帧的内部结构局部变量表认识局部变量表关于Slot的理解Slot代码示例Slot的重复利用静态变量与局部变量的对比补充说…

oracle安装教程

1安装和创建用户 1.1.安装以及常见问题 oracle安装教程 安装中 system密码改成root oracle卸载&#xff0c;除此之外清除C:\Program Files内的oracle 需要准备oracle安装包和plsql界面化操作工具 重装报错bug&#xff1a; plsql操作 plsql注册码 product code: ke4tv8t5jtxz…

java动态代理-面向切面代码样例

1.测试入口import java.lang.reflect.Proxy;/*** 面向切面测试* author epsoft-hy**/ public class test {public static void main(String[] args) {Class<?>[] cls {UserDao.class};//接口一个String classpath"util.aop.UserDaoImp";//访问类路径test2(tes…

【学vue跟玩一样】快速学会常用指令及如何理解生命周期

一&#xff0c;内置指令1.v-textv-bind:&#xff0c;单向绑定解析表达式v-model :双向数据绑定v-for:遍历数组/对象/字符串v-on :绑定事件监听,可简写为v-if :条件渲染(动态控制节点是否存存在)v-else :条件渲染(动态控制节点是否存存在)v-show:条件渲染(动态控制节点是否展示)…

3. Rstudio【可视化导入】数据

b站课程视频链接&#xff1a;https://www.bilibili.com/video/BV19x411X7C6?p1 腾讯课堂(最新&#xff0c;但是要花钱&#xff0c;我花99元买了&#xff0c;感觉不错&#xff09;&#xff1a;https://ke.qq.com/course/3707827#term_id103855009 &nbsp&#xff1b; 本笔记…

SigmaStar空板烧录

一、硬件连接 在官方给的SDK文档中&#xff0c;有描述如何使用ISP TOOL给空板烧录程序&#xff0c;但坑的是&#xff0c;文档中并没有写这个上位机工具需要配合Mstar专门的烧录工具来使用&#xff0c;烧录工具如下图所示。 上图中有三根连接线&#xff0c;示意图如下。目标板的…

HTML与CSS基础(九)—— 综合项目(CSS样式补充、项目前置认知、项目结构搭建)

目标能够在网页中使用 精灵图 能够使用 背景大小属性 &#xff0c;设置背景图片的大小 能够认识 CSS书写顺序&#xff0c;提高代码专业性和浏览器渲染性能 能够使用的专业方式完成 项目结构搭建 和 基础公共样式 能够应用已学技术知识 完成小兔鲜儿项目一、项目样式补充目标&am…

URL中绝对路径与相对路径拼接问题总结

URL中绝对路径与相对路径拼接问题总结1. 基础环境2. 测试2.1 总结2.2 本地文件url1. 基础环境 这里用nginx的docker镜像构建了一个服务&#xff0c;步骤如下&#xff1a; sudo docker pull nginxsudo docker run -d --name nginx01 -p 8083:80 nginx nginx发布的根目录是/us…

Redis安装及常用数据类型介绍

1、redis介绍1.1、redis是一个开源的key-value存储系统1.2、和Memcached类似&#xff0c;它支持存储的value类型相对很多&#xff0c;包括String、list、set、zset以及hash类型。1.3、这些数据类型都支持push/pop、add/remove及取交集并集及更丰富的操作&#xff0c;而且这些操…