Python爬取京东书籍信息(包括书籍评论数、简介等)

一. 工具

  • PyCharm
  • Scrapy
  • Chrome浏览器

二. 准备爬取的数据

items.py

import scrapy


class JdbookItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()

    book_id = scrapy.Field() #书籍ID
    book_name = scrapy.Field() #书名
    author = scrapy.Field() #作者
    Publishing_house = scrapy.Field() #出版社
    price = scrapy.Field() #价格
    book_url = scrapy.Field() #书籍链接
    comment_num = scrapy.Field() #评论数
    cover_url = scrapy.Field() #封面链接
    book_content = scrapy.Field() #书籍简介

    pass

三. 内容简述

  • 这里以爬取python书籍为例,因此以python书籍页面链接为base_url。若想要爬取其他书籍,可手动更改base_url,或者利用keword关键字构造链接模拟搜索功能
  • 书名、价格等基本信息可以在目录页面处爬取,但是评论数、书籍简介无法直接从目录页面爬取,因此需进一步寻找并构造链接

这里有两点需要注意:

  • 在目录页面中无法直接找到访问下一页的链接
  • 可以从目录页面中得到单一书籍的链接,但无法通过访问该链接直接爬取书籍的详细信息

四. 页面分析

(一) 寻找目录中商品所在标签

先在京东的商品界面选择分类:图书→计算机与网络→编程语言与程序设计→python。
然后鼠标右键选“检查”,在点击左上角形似鼠标的图标在这里插入图片描述

然后点击页面任意处,即可索引到点击处所在的标签。例如,我们点击第一本书的图片,会自动索引到该书籍图片与其封面图片所在位置
在这里插入图片描述
于是我们便找到了书籍封面链接所在的位置,即 div class=“p-img” 标签下的 a 标签下的 img 标签的 src 属性内,后面直接爬取即可。
接下来我们往下拉,发现一列有规律的li标签
在这里插入图片描述
于是我们回到上面将第一个打开的li标签收起来,发现所有的li标签都在该ul标签下在这里插入图片描述
而每一本书所能够提取的数据全部藏在它的li标签下,所以后续我们可直接提取该ul标签下的li标签列

(二) 寻找页面中能爬取到的所有数据

现在我们需要寻找其他的数据分别都在哪些标签下,然后直接提取即可。

寻找其他能够直接在目录页面下爬取的数据时,步骤与上述寻找书籍封面图片链接的步骤完全一致。

可以提取到的字段有:出版社、作者、 书籍ID 、书名、书的链接(提取后需要拼接)、封面图片链接、价格。
注: 书籍的ID在后续爬取书籍评论数和简介时需要用来拼接链接。

注: 由于要我们模拟翻页更能,所以构造链接base_url时需要有page关键字。在第一页时,链接是这样的:在这里插入图片描述
我们还不确定怎么加上page关键字,没关系,我们手动点击下一页,发现链接变成这样:
在这里插入图片描述
好了,现在可以得到base_url是:https://list.jd.com/list.html?cat=1713%2C3287%2C3797&ev=2563_22814%5E&page=

后面的部分可以不要,没什么影响。

jd_spiders.py

# -*- coding: utf-8 -*-
from jingdong.items import JdbookItem
from scrapy import Request
from scrapy.spiders import Spider
import json
import re


class JdbookerSpider(Spider):
    name = 'jdbooker'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36',
    }

    def start_requests(self):
        base_url = 'https://list.jd.com/list.html?cat=1713%2C3287%2C3797&ev=2563_22814%5E&page='
        for page in range(1, 8):
            url = base_url + str(page)
            yield Request(url, callback=self.parse, headers=self.headers)

    def parse(self, response):
        #取出该ul标签下的所有li标签,及所有商品标签
        books = response.xpath('//ul[@class="gl-warp clearfix"]/li')

        for book in books:
            item1 = JdbookItem()
            item1['book_id'] = book.xpath('./@data-sku').extract_first()
            item1['book_name'] = book.xpath('.//div[@class="p-name"]/a/em/text()').extract_first()
            #若存在作者
            if book.xpath('.//div[@class="p-bookdetails"]/span[@class="p-bi-name"]/text()'):
                item1['author'] = book.xpath('.//div[@class="p-bookdetails"]/span[@class="p-bi-name"]/a[1]/text()').extract()[0]
            else:
                item1['author'] = '/'
            #若存在出版社
            if book.xpath('.//div[@class="p-bookdetails"]/span[@class="p-bi-store"]/text()'):
                item1['Publishing_house'] = book.xpath('.//div[@class="p-bookdetails"]/span[@class="p-bi-store"]/a[1]/text()').extract()[0]
            else:
                item1['Publishing_house'] = '/'
            item1['price'] = book.xpath('.//div[@class="p-price"]/strong/i/text()').extract()
            item1['cover_url'] = book.xpath('.//div[@class="p-img"]/a/img/@src').extract_first()
            #无法通过该书籍链接进行详细信息的进一步爬取,应该是京东反爬所致
            item1['book_url'] = 'http:' + book.xpath('.//div[@class="p-name"]/a/@href').extract_first()

            #利用书籍的ID构造获取书籍评论数的链接
            url = "http://club.jd.com/clubservice.aspx?method=GetCommentsCount&referenceIds=" + str(item1['book_id'])
            yield Request(url, meta={'item': item1}, callback=self.parse_getCommentnum, headers=self.headers)

(三) 寻找评论数所在链接

这里提一下,其实本来我们是可以在目录也下找到书籍评论数所在的标签位置的,但是提取的时候却发现为空,这应该是因为评论数是动态加载的,所以无法直接获取。

还有另一点,其实我们之前已经爬到了每本书的详情链接,但是也无法直接通过该链接进入页面爬取书籍的详情,因为页面是动态加载的。

接下来我们先进入详情页面分析,右键→检查→Network→JS,然后刷新一下页面,接着→随便点一个文件→Preview。
在这里插入图片描述
接下来就得下苦功夫了,一个文件一个文件找,最终发现我们要的评论数comment_num在这个文件夹里:
在这里插入图片描述
在这里插入图片描述
查看他的request(请求)链接的形式
在这里插入图片描述
链接为:在这里插入图片描述
再打开两本书的页面找到这个链接,分别为:
在这里插入图片描述
在这里插入图片描述
发现规律:其实这里的referenceIds关键字就是前面爬取到的书籍的ID,而referenceIds关键字后面的其实是多余部分,丢弃之后发现没影响。构造链接的代码在上一块代码末尾。

打开链接看文本是怎么样的,然后上代码:在这里插入图片描述
jd_spiders.py

    def parse_getCommentnum(self, response):
        item1 = response.meta['item']
        # response.text取出response的文本
        # json.loads(str)可以将str转化为字典形式
        js = json.loads(str(response.text))
        # 取出js中的评论数
        item1['comment_num'] = js['CommentsCount'][0]['CommentCount']

        #利用书籍的ID构造获取书籍简介的链接
        content_url = 'https://dx.3.cn/desc/' + str(item1['book_id']) + '?encode=utf-8&cdn=2&callback=showdesc'
        yield Request(content_url, meta={'item': item1}, callback=self.parse_getContent, headers=self.headers)

注: 这里又利用书籍ID构造获取书籍简介的链接,进行下一步的请求。

(四) 寻找书籍简介所在链接

接着依旧是类似(三)的步骤,不过这次是在Response中看,因为Preview里面不把鼠标移过去看不到简介内容:
在这里插入图片描述
找到文件所在位置:
在这里插入图片描述
接着观察链接形式:
在这里插入图片描述
链接为:
在这里插入图片描述
同样是多打开几本书,并找到该链接来观察链接形式在这里插入图片描述
在这里插入图片描述
发现只有中间数字那个部分在发生改变,其实那就是前面爬取到的书籍ID,因此我们就可以构造链接了,构造链接的代码在上一块代码末尾。

打开链接发现需要将文本头尾的部分去掉,并将其转换为字典形式,匹配出关键字"content"对应的部分之后(该步骤也可省略,直接用正则表达式提取简介即可),此部分文本为html格式的字符串,即可用正则表达式提取出内容简介(图中深色部分):
在这里插入图片描述

这里给出提取书籍简介的代码:
jd_spiders.py

    def parse_getContent(self, response):
        item1 = response.meta['item']

        text = response.text #取出rexponse的文本
        text1 = text[9:-1] #去掉文本字符串头尾的多余部分
        js = json.loads(text1) #将剩余的字符串转化为字典形式
        content = js['content'] #提取出关键字content对应的文本

        # Selector(text=content)将字符串形式的content转化为html形式,以便用xpath()提取文本
        # 判断标签div[@class="book-detail-content"]下是否有p标签,有则进
        if Selector(text=content).xpath('.//div[@class="book-detail-content"]/p/text()').extract_first():
            introduction = Selector(text=content).xpath('.//div[@class="book-detail-content"]/p/text()').extract_first()
        else:
            introduction = Selector(text=content).xpath('.//div[@class="book-detail-content"]/text()').extract_first()
        # 这里有一个问题就是部分数据的简介页面数据很杂,标签div[@class="book-detail-content"]下除了p标签外还有br标签等,无法有效提取
        # 在xpath()里面用//text()也达不到提取效果,害 希望有人能够突破一下

        introduction = introduction.strip()  # 去掉字符串开头或结尾的空格
        if introduction:
            item1['book_content'] = introduction
        else: #若未提取到书籍简介
            item1['book_content'] = '/'
        return item1

五. 代码整合

items.py

import scrapy


class JdbookItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()

    book_id = scrapy.Field() #书籍ID
    book_name = scrapy.Field() #书名
    author = scrapy.Field() #作者
    Publishing_house = scrapy.Field() #出版社
    price = scrapy.Field() #价格
    book_url = scrapy.Field() #书籍链接
    comment_num = scrapy.Field() #评论数
    cover_url = scrapy.Field() #封面链接
    book_content = scrapy.Field() #书籍简介

    pass

jd_spiders.py

# -*- coding: utf-8 -*-
from jingdong.items import JdbookItem
from scrapy import Request
from scrapy.spiders import Spider
import json
import re


class JdbookerSpider(Spider):
    name = 'jdbooker'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36',
    }

    def start_requests(self):
        base_url = 'https://list.jd.com/list.html?cat=1713%2C3287%2C3819&page='
        for page in range(1, 8):
            url = base_url + str(page)
            yield Request(url, callback=self.parse, headers=self.headers)

    def parse(self, response):
        #取出该ul标签下的所有li标签,及所有商品标签
        books = response.xpath('//ul[@class="gl-warp clearfix"]/li')

        for book in books:
            item1 = JdbookItem()
            item1['book_id'] = book.xpath('./@data-sku').extract_first()
            item1['book_name'] = book.xpath('.//div[@class="p-name"]/a/em/text()').extract_first()
            #若存在作者
            if book.xpath('.//div[@class="p-bookdetails"]/span[@class="p-bi-name"]/text()'):
                item1['author'] = book.xpath('.//div[@class="p-bookdetails"]/span[@class="p-bi-name"]/a[1]/text()').extract()[0]
            else:
                item1['author'] = '/'
            #若存在出版社
            if book.xpath('.//div[@class="p-bookdetails"]/span[@class="p-bi-store"]/text()'):
                item1['Publishing_house'] = book.xpath('.//div[@class="p-bookdetails"]/span[@class="p-bi-store"]/a[1]/text()').extract()[0]
            else:
                item1['Publishing_house'] = '/'
            item1['price'] = book.xpath('.//div[@class="p-price"]/strong/i/text()').extract()
            item1['cover_url'] = book.xpath('.//div[@class="p-img"]/a/img/@src').extract_first()
            #无法通过该书籍链接进行详细信息的进一步爬取,应该是京东反爬所致
            item1['book_url'] = 'http:' + book.xpath('.//div[@class="p-name"]/a/@href').extract_first()

            #利用书籍的ID构造获取书籍评论数的链接
            url = "http://club.jd.com/clubservice.aspx?method=GetCommentsCount&referenceIds=" + str(item1['book_id'])
            yield Request(url, meta={'item': item1}, callback=self.parse_getCommentnum, headers=self.headers)


    def parse_getCommentnum(self, response):
        item1 = response.meta['item']
        # response.text取出response的文本
        # json.loads(str)可以将str转化为字典形式
        js = json.loads(str(response.text))
        # 取出js中的评论数
        item1['comment_num'] = js['CommentsCount'][0]['CommentCount']

        #利用书籍的ID构造获取书籍简介的链接
        content_url = 'https://dx.3.cn/desc/' + str(item1['book_id']) + '?encode=utf-8&cdn=2&callback=showdesc'
        yield Request(content_url, meta={'item': item1}, callback=self.parse_getContent, headers=self.headers)

这部分代码本来应该写在上面的JdbookerSpider类里面,但是发现代码太长的话手机端显示不全,没办法所以把这个函数写在下面。
jd_spiders.py

    def parse_getContent(self, response):
        item1 = response.meta['item']

        text = response.text #取出rexponse的文本
        text1 = text[9:-1] #去掉文本字符串头尾的多余部分
        js = json.loads(text1) #将剩余的字符串转化为字典形式
        content = js['content'] #提取出关键字content对应的文本
        #剔除一些无用的html文本标签
        content = re.sub('<a.*?>|</a>|<p.*?>|</p>|<br.*?>|</br>|<div>', '', content)
        #正则表达式匹配书籍的内容简介
        book_content = re.findall('.*?>内容简介<.*?<div class="book-detail-content">(.*?)</div>', content, re.S)

        introduction = book_content[0].strip()
        #剔除空字符串,如空格与换行符\n等
        introduction = re.sub('\s', '', introduction)
        if introduction:
            item1['book_content'] = introduction
        else: #若未提取到书籍简介
            item1['book_content'] = '/'
        return item1

setting.py

FEED_EXPORT_ENCODING = 'gb18030' #解决csv的乱码情况
  • 6
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用Python爬取京东评论,可以按照以下步骤进行操作: 1. 首先,在京东网站(jd.com)中搜索您想要抓取评论商品,并打开该商品面。 2. 复制商品面的链接,并提取其中的商品ID。例如,您可以使用链接"https://item.jd.com/10902370587.html",提取出商品ID为10902370587。 3. 使用提取到的商品ID,拼接生成商品评论的链接。根据引用的示例,生成的链接形式为:"https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=10902370587&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1"。 4. 根据需要,您可以调整链接中的参,例如评分(score)、排序方式(sortType)、每评论量(pageSize)等。 5. 使用Python中的网络请求库(例如requests)发送GET请求,获取评论面的HTML内容。您可以使用Python的代码来实现这一步骤。 6. 对获取到的HTML内容进行解析,提取出评论内容和其他相关信息。您可以使用Python中的HTML解析库(例如BeautifulSoup)来实现这一步骤。 7. 可以根据需要,将提取到的评论内容存储到据库或者其他文件中,进行进一步的分析或使用。 需要注意的是,根据引用中的说明,京东评论面的评论据分布在多个中,可以使用多线程或其他方式进行并发爬取,以提高爬取效率。 希望以上信息对您有帮助!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python爬取京东商品评价信息](https://blog.csdn.net/qq_45637241/article/details/112306597)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [利用python爬取京东平台评论及图片并进行分析](https://blog.csdn.net/HUANGliang_/article/details/119675007)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值