京东店铺公司名爬虫

news2024/12/26 9:31:59

内容仅供学习参考,如有侵权联系删除

先通过京东非自营的店铺名拿到的公司名,再通过公司名称去其他平台拿到联系方式(代码省略)


from aioscrapy.spiders import Spider
from aioscrapy.http import Request, FormRequest
import ddddocr
import re
import random

from loguru import logger


class JingDongSpider(Spider):
    name = 'products:jd'

    custom_settings = {
        'CONCURRENT_REQUESTS': 4,
        # 'DOWNLOAD_DELAY': 0.5,
        'DOWNLOAD_TIMEOUT': 10,
        'RETRY_TIMES': 5,
        'HTTPERROR_ALLOWED_CODES': [503],
        'COOKIES_ENABLED': False,
        'DUPEFILTER_CLASS': 'aioscrapy.dupefilters.redis.RFPDupeFilter',  # 过滤方法
        # 'LOG_LEVEL': 'DEBUG'
    }

    ocr = ddddocr.DdddOcr(show_ad=False, use_gpu=True)

    async def start_requests(self):

        yield Request(
            url=f"https://mall.jd.com/index-11111111.html?from=pc",
            method='GET',
            dont_filter=False,
            # fingerprint=str(i),
            # meta={"shop_id": str(i)},
            priority=500)

    async def parse(self, response):
        """店铺首页"""
        title = response.xpath('//title/text()').get() or ''
        shop_id = str(response.meta['shop_id'])
        if '您所访问的页面不存在' in str(title) or len(response.text) < 25000:
            logger.info(f"{shop_id}")
            return

        logger.info(title.strip())
        product_list = self.get_product_items(response)
        urls = re.findall(r"//\w+\.jd\.com/view_search-\d+-\d+-\d+-\d+-\d+-\d+\.html", response.text)

        yield Request(
            url=f"https://mall.jd.com/sys/vc/createVerifyCode.html?random={random.random()}",
            method='GET',
            callback=self.parse_img_code,
            dont_filter=True,
            meta={
                "data": {"product_url": 'https:' + urls[0] if urls else '',
                         "categorys": self.get_category(response),
                         "product_list": product_list,
                         # "shop_url": response.url,
                         "shop_id": shop_id}
            },
            priority=500)

    async def parse_img_code(self, response):
        """验证码"""
        code = self.ocr.classification(response.body)
        cookie = dict(response.cookies.items())
        shop_id = response.meta["data"]["shop_id"]
        if not code or not cookie:
            return

        yield FormRequest(
            url=f'https://mall.jd.com/showLicence-{shop_id}.html',
            method='POST',
            formdata={"verifyCode": str(code)},
            cookies=cookie,
            meta={"data": response.meta["data"]},
            callback=self.parse_shop_detail,
            dont_filter=True,
            priority=400)

    async def parse_shop_detail(self, response):
        """ 解析店铺详情
        """
        company = response.xpath(
            '//*[contains(.,"企业名称:")]/following-sibling::span[position()=1]/text()').get() or ''
        shop_name = response.xpath(
            '//*[contains(.,"店铺名称:")]/following-sibling::span[position()=1]//text()').get() or ''
        shop_url = response.xpath('//*[contains(.,"店铺网址:")]/following-sibling::span[position()=1]//text()').get()
        # legal_person = response.xpath( '//*[contains(.,"法定代表人姓名:")]/following-sibling::span[position()=1]//text()').get()
        # business_scope = response.xpath( '//*[contains(.,"营业执照经营范围:")]/following-sibling::span[position()=1]//text()').get()
        license = response.xpath('//img[@class="qualification-img"]/@src').get() or ''
        if not company or '测试' in shop_name or '测试' in company:
            if not company:
                logger.info(f"无公司: {response.url}")
            else:
                logger.info(f" {shop_name} => {company}")
            return
        else:
            logger.info(company)

        data = response.meta['data']
        data['company'] = company
        data['shop_name'] = shop_name

        items = dict(company=company,
                     shop_name=shop_name,
                     shop_url='https:' + shop_url if shop_url else response.url,
                     product_url=data['product_url'],
                     shop_id=data['shop_id'],
                     push_kafka_status=0,
                     license='https:' + license if license else '',

                     )

        if len(data['product_list']) < 1:
            if data['product_url']:
                yield Request(
                    url=data['product_url'],
                    method='GET',
                    meta={"data": data},
                    callback=self.parse_product,
                    dont_filter=True,
                    priority=300)
            else:
                logger.warning(f"获取不到产品链接:{response.url}")
                items.pop('product_url')
            yield items

        else:
            product_list = []
            for item in data['product_list']:
                item['entityId'] = company
                product_list.append(item)

            yield dict(
                source='jd.com',
                ocid='',
                entityId=company,
                product=product_list,
            )
            items['push_kafka_status'] = 1
            yield items

    async def parse_product(self, response):
        """解析产品页"""
        data = response.meta['data']
        shop_name = data['shop_name']
        company = data['company']
        categorys = data['categorys']

        product_list = self.get_product_items(response, shop_name, company, categorys, data['product_url'])

        if product_list:
            yield dict(
                source='jd.com',
                ocid='',
                entityId=company,
                product=product_list,
            )
            logger.info(f"成功: {company} => {data['shop_id']}")

            yield dict(
                company=company,
                shop_id=data['shop_id'],
                push_kafka_status=1,

            )
        else:
            logger.error(f"{response.url} => {data['shop_id']}")

    def get_product_items(self, response, shop_name='', company='', categorys='', shop_url='') -> list:
        ul = response.xpath('//li[@class="jSubObject"] | //li[@class="jSubObject gl-item"] | //div[@class="jItem"]')

        product_list = []
        for li in ul[:10]:
            title = li.xpath('.//div[@class="jDesc"]/a/@title').get() or ''
            # price = li.xpath('.//span[@class="jdNum"]/text()').get()
            img = str(li.xpath('.//div[@class="jPic"]//img/@src').get() or '').replace('s350x350', '')
            if not title and not img:
                continue
            if img:
                img = re.sub(r"/n[23456789]/", "/n1/", img)
                img = 'https:' + img

            item_i = {}
            item_i["entityId"] = company
            item_i["productPic"] = img.replace('s350x350', '')
            item_i["productName"] = title  # 产品名称
            item_i["productCategory"] = ""  # 产品分类
            item_i["productKeyword"] = ""  # 产品关键词
            item_i["productPrice"] = ""  # 产品价格
            item_i["mainProducts"] = categorys  # 主营产品
            item_i["listingPlatform"] = "京东"
            item_i["productShopName"] = shop_name  # 产品所属店铺名
            item_i["dataLink"] = shop_url or response.url  # 店铺链接
            product_list.append(item_i)

        return product_list

    @staticmethod
    def get_category(response) -> str:
        categorys = response.xpath(
            '//ul[@class="menu-list"]/li[@class="menu"]/a/text() | //div[@class="abs"]//div[@class="ins abs hdur_2"]/a/text()').getall()
        category = []
        for i in categorys:
            if '首页' in i or '全部' in i or '所有' in i or '问题' in i or '指导' in i or '售后' in i or '撰文' in i:
                continue
            category.append(i)
        return ','.join(category)


if __name__ == '__main__':
    JingDongSpider.start()

最后的数据

在这里插入图片描述

本内容仅限用于学习参考,不得用于商业目的。如有版权问题,请联系我们删除,谢谢!
欢迎一起学习讨论Q540513871

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

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

相关文章

【LeetCode75】第七十四题 每日温度

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们一个数组&#xff0c;表示每天的温度&#xff0c;要我们返回一个同样长度的数组&#xff0c;答案里装着当前气温的下一个更高气…

Linux用户管理与远程管理

一、用户管理 1、回顾用户组管理 groupadd &#xff1a;组添加 groupmod&#xff1a;组修改 groupdel&#xff1a;组删除 与用户组相关的文件/etc/group&#xff0c;一共拥有4列 itheima:x:1000: 1-组名称 2-组密码 3-组编号 4-组内用户信息&#xff08;这个组必须是这个…

阿里云优惠口令(2023更新)

2023年阿里云域名优惠口令&#xff0c;com域名续费优惠口令“com批量注册更享优惠”&#xff0c;cn域名续费优惠口令“cn注册多个价格更优”&#xff0c;cn域名注册优惠口令“互联网上的中国标识”&#xff0c;阿里云优惠口令是域名专属的优惠码&#xff0c;可用于域名注册、续…

微信公众号粉丝迁移步骤?

公众号迁移有什么作用&#xff1f;只能变更主体吗&#xff1f;公众号迁移是将原公众号的粉丝、违规记录、文章和素材库&#xff08;可选&#xff09;迁移至一个新的公众号。整体流程较为复杂&#xff0c;需花费7-10天。通过公众号迁移功能可以将A账号的粉丝、文章素材&#xff…

ROS工具RViz可视化3D空间的一些错误的解决方案

1、引言 RViz是ROS的一个可视化3D空间的工具&#xff0c;它用于帮助用户在ROS系统中导航、查看和交互。RViz可以显示来自各种ROS节点的信息&#xff0c;例如传感器数据、机器人的状态和路径等。通过RViz&#xff0c;用户可以以图形方式查看和交互各种ROS数据&#xff0c;非常直…

连锁药店的自有品牌之争:老百姓大药房能否突围?

文丨新熔财经 作者丨楷楷 近年来&#xff0c;随着医保谈判药品的“双通道”&#xff08;即消费者可在有资质的药店买到新进医保的创新药&#xff09;&#xff0c;以及“门诊统筹”将药店纳入医保报销等医改政策出台&#xff0c;药企开始重新重视起零售药店渠道&#xff0c;很…

C++对象模型(18)-- 函数语义学:函数调用过程

1、栈帧结构 函数执行是通过系统栈来实现的&#xff0c;系统栈分为若干个栈帧。 栈帧就是函数运行的环境&#xff0c;每个函数在被调用时都会在系统栈区形成一个叫栈帧的结构。一次函数调用相关的数据保存在栈帧中&#xff0c;比如函数参数、函数的局部变量、函数执行完后的返…

Leetcode 21 合并两个有序链表 (链表)

Leetcode 21 合并两个有序链表 &#xff08;链表&#xff09; 解法1 复杂的第一版本&#xff08;优化大于和等于合并见方法二&#xff09;解法2 注意注意&#xff1a;先添加元素toadd.next list1&#xff0c;添加之后才可以移动指针toadd toadd.next 解法1 复杂的第一版本&a…

数字电路常用芯片合集

前言 本文归纳了本科数字电路中常见的芯片型号及其功能&#xff0c;分为以下几类&#xff1a; 组合逻辑电路芯片 时序逻辑电路芯片 D/A A/D相关芯片 组合逻辑电路芯片 优先编码器74HC148 功能&#xff1a;多→1&#xff0c;选通 逻辑框图 功能表 补充&#xff1a;可以…

react native 使用夜神模拟器开发调试 windows+android

执行adb devices, 提示List of devices attached 打开本地sdk目录中的platform-tools文件夹&#xff0c;复制下面3个文件 打开夜神模拟器安装目录中的bin目录&#xff0c;把复制出来的文件复制替换到bin目录中 在复制一份platform-tools目录中的adb.exe&#xff0c;重命名为…

java最新Springboot3+微服务实战12306高性能售票系统全套开发课程

java最新Springboot3微服务实战12306高性能售票系统全套开发课程 视频课程在文末获取 第1章 课程介绍与学习指南。 1-1 课前必读&#xff08;不读错过一个亿&#xff09; 1-2 课程导学 1-3 为什么要选择最新版本SpringBoot3和JDK17&#xff1f; 1-4 在线demo网站演示 第2…

现货黄金的走势怎么看

成功的现货黄金交易者&#xff0c;都有自己一套的看行情的方法&#xff0c;以及自己最熟悉的交易获利机会&#xff0c;这使他们获利的胜率能够保持在一定的水平之上&#xff0c;长远来说&#xff0c;这也使他们成为市场上的赢家。 现货黄金的价格走势总在不断的变化之中&#x…

GEE:绘制土地利用类型面积分布柱状图

作者:CSDN @ _养乐多_ 本文记录了,在 Google Earth Engine (GEE)中进行随机森林分类后绘制不同类型面积分布柱状图的代码片段。 完整代码请看博客《GEE:随机森林分类教程(样本制作、特征添加、训练、精度、参数优化、贡献度、统计面积)》 柱状图效果如下所示, 文章目…

Pulsar-Pulsar 之 Functions

Pulsar 之 Functions Pulsar FunctionsPulsar Functions是什么&#xff1f;为什么使用Pulsar Functions&#xff1f;实例 完全限定函数名函数实例函数workerFunctions 运行时处理保证和订阅类型上下文函数消息类型Window functionwindow的类型快速开始启用有状态的函数使用Puls…

通讯协议学习之路:RS485协议理论

通讯协议之路主要分为两部分&#xff0c;第一部分从理论上面讲解各类协议的通讯原理以及通讯格式&#xff0c;第二部分从具体运用上讲解各类通讯协议的具体应用方法。 后续文章会同时发表在个人博客(jason1016.club)、CSDN&#xff1b;视频会发布在bilibili(UID:399951374) 序&…

接口测试vs功能测试

接口测试和功能测试的区别&#xff1a; 本文主要分为两个部分&#xff1a; 第一部分&#xff1a;主要从问题出发&#xff0c;引入接口测试的相关内容并与前端测试进行简单对比&#xff0c;总结两者之前的区别与联系。但该部分只交代了怎么做和如何做&#xff1f;并没有解释为什…

“一键替换视频封面,高效批量剪辑从未如此简单

在一个充满竞争和创意的世界&#xff0c;吸引人的视频封面往往能够决定内容的成败。今天&#xff0c;我将向大家介绍一种可以轻松替换视频封面图片的实用技巧&#xff0c;让你在创作中更胜一筹&#xff01; 首先&#xff0c;我们要进入媒体梦工厂主页面&#xff0c;并点击“视…

Go语言入门心法(十一): 文件处理

Go语言入门心法(一): 基础语法 Go语言入门心法(二): 结构体 Go语言入门心法(三): 接口 Go语言入门心法(四): 异常体系 Go语言入门心法(五): 函数 Go语言入门心法(六): HTTP面向客户端|服务端编程 Go语言入门心法(八): mysql驱动安装报错onnection failed Go语言入门心法(…

Java中的代码重构:技巧、优秀实践与方法

什么是 Java 代码重构&#xff1f; Java 代码重构是一种在不影响代码外部行为的前提下进行的代码优化&#xff0c;它通过渐进和小规模的优化来改善现有代码的结构和质量。重构的目标是提高代码的可读性、性能、可维护性和效率等。 Martin Fowler 是这个领域的权威的大牛和非常…

前端 js 之 代码执行的一个过程 02

嘿&#xff0c;欢迎你来 &#xff01;&#x1f495; 文章目录 前言一、运行一个 js 文件二、运行环境三、js执行代码的过程&#xff08;普通变量&#xff09;四、打印 window五、js执行代码的过程&#xff08;函数变量&#xff09;六、函数调用函数的过程注意&#xff01;&…