Python爬虫:爬取京东商品评论(处理json) urllib3+bs4+sqlite3

news/2024/7/19 9:13:03 标签: python, 爬虫, urllib3, beautifulsoup4, json

通过观察京东商品页面返回的评论数据是 JSON 格式的,所以抓取指定评论需要使用 JSON 模块中相应的 API 进行分析,而从搜索页面抓取的商品列表需要分析 HTML 代码,所以使用 bs4。在对数据进行分析整理后,需要将数据保存到 sqlite 数据库中,其他模块还包括 os 和 fake_useragent(获取假的消息头,之前用一个消息头好像被封了,带秀)。

python">from urllib3 import *
import sqlite3
import json
import os
from bs4 import BeautifulSoup
from fake_useragent import UserAgent

首先我们来到京东随便搜索一个商品,并且进入商品具体页面,检测network

不难发现这个页面获取了评论有关的json数据:

将此 url 在浏览器中访问后

这并不是纯粹的 json 数据,前面还有 fetchJSON_comment...,以及其他一些不属于 JSON 数据的内容,通过不同的商品面叶可以发现 callback 参数的值基本上都不同,回调函数,不妨去掉试试

哈!果然能正常访问,而且内容中也没有了fetchJSON_啥啥啥的,这又方便了不少

于是我们得到了一个基本格式https://sclub.jd.com/comment/productPageComments.action?productId=***&score=0&sortType=5&page=***&pageSize=10&isShadowSku=0&fold=1,不过要注意的是第一页是0

当然其中还有一些零碎的地方需要转为json类型格式(需要将null,false,true用双引号括起来),可以直接通过字符串替换的方式,然后将json数据转换为字典对象

python">def getRateDetail(productId, page):
    url = 'https://sclub.jd.com/comment/productPageComments.action?productId='+ str(productId) + '&score=0&sortType=5&page='+str(page)+'&pageSize=10&isShadowSku=0&fold=1'
    r = http.request('GET', url, headers=head)
    c = r.data.decode('GB18030')
    c = c.replace('null', '"null"')
    c = c.replace('false', '"false"')
    c = c.replace('true', '"true"')
    # 将json数据转换为字典对象
    jdjson=json.loads(c)
    return jdjson

并且在此页上有页数信息

以下为获取每个商品页最大评论页数

python">#获取具体商品的最后一页
def getLastPage(productId):
    jdjson = getRateDetail(productId,1)
    return jdjson['maxPage']

接下来的任务就是抓取搜索页面的所有商品id,商品页网址如https://item.jd.com/5734174.html,不难猜测5734174就是商品id,来到搜素页

可见每个li标签中的data-sku就是商品id,接下来自然就是通过美汤来获取所有商品id的列表

python"># 以列表形式返回商品ID
def getProductIdList():
    url='https://search.jd.com/Search?keyword=cherry&enc=utf-8&wq=cherry&pvid=2db50b439b0747408233915adca72e88'
    r = http.request('GET', url, headers=head)
    #注意如果搜索的内容有中文,网址中就会有utf8的东西,需要ignore忽略utf8一下
    c = r.data.decode('GB18030','ignore').encode('utf8')
    soup = BeautifulSoup(c, 'html.parser')
    liList=soup.find_all('li',attrs={'class':'gl-item'})
    idList = []
    for li in liList:
        idList.append(li['data-sku'])
    #去掉重复的id,不过应该不会重复(利用Set的特性)
    idList = list(set(idList))
    return idList

最后便是加入到sqlite数据库(注意执行完要commit一下)当中了

完整代码:

python">from urllib3 import *
import sqlite3
import json
import os
from bs4 import BeautifulSoup
from fake_useragent import UserAgent

disable_warnings()
http = PoolManager()

head = {
    'User-Agent': str(UserAgent().random)
}

dbPath = 'jdkb.sqlite'
if os.path.exists(dbPath):
    os.remove(dbPath)
conn = sqlite3.connect(dbPath)
cursor = conn.cursor()
cursor.execute('''create table kb_comment
            (id integer primary key autoincrement not null,
            content text not null,
            ctime text not null,
            productName text not null);''')
conn.commit()


#获取具体商品的json数据
def getRateDetail(productId, page):
    url = 'https://sclub.jd.com/comment/productPageComments.action?productId='+ str(productId) + '&score=0&sortType=5&page='+str(page)+'&pageSize=10&isShadowSku=0&fold=1'
    r = http.request('GET', url, headers=head)
    c = r.data.decode('GB18030')
    c = c.replace('null', '"null"')
    c = c.replace('false', '"false"')
    c = c.replace('true', '"true"')
    jdjson=json.loads(c)
    return jdjson


#获取具体商品的最后一页
def getLastPage(productId):
    jdjson = getRateDetail(productId,1)
    return jdjson['maxPage']

# 以列表形式返回商品ID
def getProductIdList():
    url='https://search.jd.com/Search?keyword=cherry&enc=utf-8&wq=cherry&pvid=2db50b439b0747408233915adca72e88'
    r = http.request('GET', url, headers=head)
    c = r.data.decode('GB18030','ignore').encode('utf8')
    soup = BeautifulSoup(c, 'html.parser')
    liList=soup.find_all('li',attrs={'class':'gl-item'})
    idList = []
    for li in liList:
        idList.append(li['data-sku'])
    #去掉重复的Utl
    idList = list(set(idList))
    return idList



init = 0
productIdList=getProductIdList()
while init < len(productIdList):
    try:
        productId = productIdList[init]
        maxPage = getLastPage(productId)
        page = 0
        while page <= maxPage:
            try:
                jdjs=getRateDetail(productId,page)
                rateList = jdjs['comments']

                n=0
                while n<len(rateList):
                    content = str(rateList[n]['content'])
                    time = str(rateList[n]['creationTime'])
                    productName = str(rateList[n]['referenceName'])
                    cursor.execute('''insert into kb_comment(content,ctime,productName)
                        values('%s','%s','%s')'''%(content,time,productName))
                    conn.commit()
                    n += 1
                page += 1
            except Exception as e:
                continue
        init+=1
    except Exception as e:
        print(e)

效果如图

···

由于sqlite一次只能 insert 500条记录,要是想爬大量数据要么分多次爬,要么就使用多线程爬虫python线程我还没看,过几天再改改吧:D


http://www.niftyadmin.cn/n/1033159.html

相关文章

Quartz任务调度笔记

一、概念 1.1简介 Quzrtz是OpenSymphony开源组织在Job scheduling领域的开源项目 特点&#xff1a;Quartz具有丰富特性的"任务调度库"&#xff0c;能够集成于任何的Java应用&#xff0c;小到独立的应用&#xff0c;大到电子商业系统。quartz能够创建亦简单亦复杂的调…

Python爬虫:爬取免费代理ip

之前写的几个爬虫都只能爬取到少量的信息&#xff0c;这是由于一个ip频繁地访问网站&#xff0c;会被认定为非正常的爬虫从而被屏蔽&#xff0c;这时候就需要使用代理ip来访问网站了&#xff0c;具体方法就是在发送request时添加一个proxy参数。代理ip有收费的也有免费的&#…

Python爬虫:多线程下载图片

目标&#xff1a;下载豆瓣热门电影封面&#xff0c;网址&#xff1a;https://movie.douban.com/explore#!typemovie&tag%E7%83%AD%E9%97%A8&sortrecommend&page_limit20&page_start0 思路&#xff1a;分析请求数据获取全部热门电影相关信息&#xff0c;通过ur…

Python爬虫:全国大学招生信息(一):爬取数据 (多进程、多线程、代理)

无聊爬爬&#xff0c;仅供学习&#xff0c;无其他用途 这几天在高考派&#xff08;http://www.gaokaopai.com/&#xff09;上爬招生信息&#xff0c;其中也绕了不少弯路也学到了许多。 以下为涉及到的模块 import requests from fake_useragent import UserAgent from multip…

Python爬虫:全国大学招生信息(二):生源数据分析(matplotlib)

在上一篇博客&#xff08;https://blog.csdn.net/qq_39192827/article/details/87136836&#xff09;中爬取了6W条json数据&#xff0c;接下来通过2D可视化来分析这些数据。需要使用的是matplotlib模块。 之前我们获取了一个大学名字对应url的txt&#xff0c;通过大学名字去6w…

Python爬虫:深度、广度(多线程)爬取网页链接并控制层级

在使用爬虫爬取多个页面时&#xff08;比如爬取邮箱&#xff0c;手机号等&#xff09;&#xff0c;一般层级越高与我们原始目标数据之间准确率越低&#xff0c;所以很有必要控制爬取层级达到有效爬取 无论是深度还是广度爬取&#xff0c;都需要以下变量和方法 #链接的正则表达…

Python:第六次全国人口普查数据分析及可视化(pandas、matplotlib)

一、数据获取 在国家统计局网中下载第六次人口普通统计表&#xff1a;http://www.stats.gov.cn/tjsj/pcsj/rkpc/6rp/indexch.htm 然后通过pandas将excel数据解析为多级字典 先观察excel数据 可以转化为这样的多级词典&#xff1a; 理清字典关系后代码就简单了 def getDataD…

八大排序算法浅析(Java)

目录 一、选择排序 1、直接选择排序 2、堆排序 二、交换排序 1、冒泡排序 2、快速排序 三、插入排序 1、直接插入排序 2、希尔排序 三、归并排序 四、基数排序 附&#xff1a;八大排序算法比较 关于Java中的排序算法&#xff0c;此篇讨论的都是内部排序&#xff0c…