目标:对常见手机应用商店评论进行爬取,对第三方数据网上的评论数据进行爬取

1. 爬虫

爬虫过程:获取评论数据→写入数据库

1.1 静态网页爬虫:requests库

以某应用商店的outlook页面为例:
  1. 在打开的应用页面右键点击检查,然后刷新一下页面,选中network,再选中Fetch/XHR,发现有一个网页评论数据url(下图3)
  2. 复制该url在新的页面打开,发现就是我们需要的评论数据,只是被编码过(没关系)
  3. 继续分析该url:http://app.so.com/message/index?page=1&requestType=ajax&_t=1661237476289&name=Outlook+Android_com.microsoft.office.outlook,经过测试发现:
    &_t=1661237476289是时间戳,去掉后不影响返回结果;
    page=1是我们请求的评论页数,可以自行更换(后面爬虫就是对page进行遍历)
    &name=Outlook+Android_com.microsoft.office.outlook是应用的名字。
  4. 然后我们就可以使用requests.get(url)方法,获取该url返回的评论数据,利用json.loads(res.text)方法读取返回的文字内容。
    import requests
    import jsonheaders = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
    }
    res = requests.get('http://app.so.com/message/index?page=1&requestType=ajax&_t=1661237476289&name=Outlook+Android_com.microsoft.office.outlook', headers=headers)
    # 加载评论内容
    json_str = json.loads(res.text)
    

完整代码如下

import requests
import json
import pymysqlheaders = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
}
# 要爬取的应用url
appname = {'Outlook':'Outlook+Android_com.microsoft.office.outlook','Office':'Office+Mobile+for+Office+365+Android_com.microsoft.office.officehub',
}# 连接数据库db = pymysql.connect(host="127.0.0.1", # 本机地址port=3306, # 默认端口user='root',    #在这里输入用户名password='root',     #在这里输入密码database='comments', # 数据库名charset='utf8mb4')cursor = db.cursor() #创建游标对象,用于数据库操作for k,v in appname.items():# 遍历应用列表for i in range(100): # 爬取前100页# 获取请求网页内容res = requests.get('http://app.so.com/message/index?page='+str(i)+'&requestType=ajax&name='+str(v), headers=headers)# 如果获取页面为[],表明无内容if res.content == b'\n\n\n[]':break# 加载评论内容json_str = json.loads(res.text) for item in json_str:# 通过msgid判断是否在数据库已存在此条数据querysql = "select msgid from database_comments_360 where msgid="+pymysql.converters.escape_string(str(item.get('msgid')))if(cursor.execute(querysql)==0):# execute(querysql)返回的是操作影响的行数sql = 'insert into database_comments_360(date,user,content,score,version,name, msgid) values(%s,%s,%s,%s,%s,%s,%s);'date = pymysql.converters.escape_string(item.get('create_time')) # 获取数据user = pymysql.converters.escape_string(item.get('username'))content = pymysql.converters.escape_string(item.get('content'))score = pymysql.converters.escape_string(str(item.get('score')))version = pymysql.converters.escape_string(str(item.get('version_name')))msgid = pymysql.converters.escape_string(str(item.get('msgid')))name = pymysql.converters.escape_string(str(k))data = [date,user,content,score,version,name,msgid]cursor.execute(sql,data)     # 插入数据db.commit() # 提交命令 (如果不提交,不会进行数据库操作)print('爬取'+str(k)+'应用评论'+str(i)+'页')cursor.close() db.close()  #关闭数据库连接

1.2 动态网页爬虫:selenium库

selenium是一个web测试工具,可以模拟浏览器操作,如打开网页,点击元素等。

在使用selenium前需要安装浏览器版本对应的chromedriver,解压后把chromedriver.exe的路径加入用户变量Path中

  1. 对某第三方网站的评论页面url进行分析:
    某发烧厂商店edge评论:https://app.diandian.com/app/6njqcmu6xj0rip4/android-review?system=4&market=3&summer=
    某蓝厂商店edge评论:https://app.diandian.com/app/rn6vtpukqjzvhw4/android-review?system=4&market=4&summer=
    发现只有两部分不一样,分别是应用名字和market,而&summer=经过测试可以删掉,不影响返回结果。这样我们就获得了需要的url。
  2. 在页面点击右键,选中检查,发现该网站使用js动态加载数据,无法像静态网页一样通过url获取评论数据。
  3. 点击element,用鼠标选中评论数据数据所在的位置,也就是左侧的表格,可以看到右侧有评论数据内容,我们就可以通过css选择器来定位到该数据:
  4. 同样也可以定位到用户评分和用户名等内容,如下图所示:
  5. 我们可以使用selenium中By.CSS_SELECTOR来定位到我们需要的元素,css样式通过下图中copy selector来获取。
  6. 分析完成后,使用selenium中的webdriver模拟对浏览器进行操作
    from selenium import webdriver # 模拟浏览器操作
    from selenium.webdriver.common.by import By # 后面用By里面的css选择器定位网页元素driver = webdriver.Chrome()# 初始化一个浏览器对象
    driver.get("https://app.diandian.com/app/4q3uzuzpe5x8es7/ios-review?system=4") # 打开网页table=driver.find_element(By.CSS_SELECTOR,'#commentContent > div.loading-wrap > div > div > div > table')#使用css定位网页表格位置
    #获取表格包含的行,并将行数赋值
    time.sleep(2)
    table_rows=table.find_elements(By.CSS_SELECTOR,'#commentContent > div.loading-wrap > div > div > div > table > tbody > tr')# table包含行数的集合,包含标题
    print('table_rows',table_rows)vrows=len(table_rows)#将总行数赋给变量vrows,后面对每一行进行遍历
    print('vrows',vrows)# 对表格进行按行遍历
    for table_num in range(1, vrows):time.sleep(2)# 爬取评论内容content = driver.find_element(by=By.CSS_SELECTOR, value="#commentContent > div.loading-wrap > div > div > div > table > tbody > tr:nth-child("+str(table_num)+") > td:nth-child(2) > div > div > div.dd-word-wrap > div > p > span").text# 爬取评论分数time.sleep(2)score = driver.find_element(by=By.CSS_SELECTOR, value="#commentContent > div.loading-wrap > div > div > div > table > tbody > tr:nth-child("+str(table_num)+") > td:nth-child(1) > div.dd-table-cell > div > div").get_attribute("aria-valuenow")
    

完整代码如下:

# diandian.py 文件
from selenium import webdriver # 模拟浏览器操作
from selenium.webdriver.common.by import By # 后面用By里面的css选择器定位网页元素
import pymysql # 对MySQL数据库进行连接、插入数据等操作def myscrapy(urls,market,appname): # 这里封装了函数,需要传入三个参数,分别是应用的url,market哪个应用市场,appname是数据库表名,指示要写入哪个数据库表driver = webdriver.Chrome()# 初始化一个浏览器对象# 连接数据库db = pymysql.connect(host="127.0.0.1", port=3306,user='root',    #在这里输入用户名password='root',     #在这里输入密码database='comments', #数据库名charset='utf8mb4')cursor = db.cursor() #创建游标对象# 删除表中数据 (非必需模块,每次爬取都先删除数据库中已有部分,重新爬取)sql='truncate table database_comments_'+str(appname)+';'cursor.execute(sql)   db.commit()for k,v in urls.items():# 遍历要爬取的应用urlsdriver.get("https://app.diandian.com/app/"+str(v)+"/android-review?market="+str(market)+"&summer=") # 打开网页# 爬前10页for i in range(10):print("正在爬取第",i,"页")# 点击下一页if (i!=0): # 在第一页之后的页面,爬取之前需要点击当前页面的‘下一页’按钮,刷新后再进行爬取try:#try处理部分应用只有一页评论,没有nextbutton按钮next_button = driver.find_element(by=By.CSS_SELECTOR, value="#commentContent > div.loading-wrap > div > div > div > div > div > button.btn-next")disable = next_button.get_attribute("disabled")# 如果下一页按钮可用再点击,否则跳出此次循环if(disable!='true'):next_button.click()print("next page")else: print("没有点击下一页")breakexcept:break# 开始爬表格数据 sleep是为了防止刷新过快,页面元素失效无法获取time.sleep(2) table=driver.find_element(By.CSS_SELECTOR,'#commentContent > div.loading-wrap > div > div > div > table')#使用css定位网页表格位置#获取表格包含的行,并将行数赋值time.sleep(2)table_rows=table.find_elements(By.CSS_SELECTOR,'#commentContent > div.loading-wrap > div > div > div > table > tbody > tr')# table包含行数的集合,包含标题                                        print('table_rows',table_rows)vrows=len(table_rows)#将总行数赋给变量vrows,后面进行循环print('vrows',vrows)for table_num in range(1, vrows):time.sleep(2)# 爬取评论内容try:content = driver.find_element(by=By.CSS_SELECTOR, value="#commentContent > div.loading-wrap > div > div > div > table > tbody > tr:nth-child("+str(table_num)+") > td:nth-child(2) > div > div > div.dd-word-wrap > div > p > span").textprint('content:',content)                             except:continue  # 爬取评论分数time.sleep(2)score = driver.find_element(by=By.CSS_SELECTOR, value="#commentContent > div.loading-wrap > div > div > div > table > tbody > tr:nth-child("+str(table_num)+") > td:nth-child(1) > div.dd-table-cell > div > div").get_attribute("aria-valuenow")print('score:',score)                            # 爬取评论时间time.sleep(2)date = driver.find_element(by=By.CSS_SELECTOR, value="#commentContent > div.loading-wrap > div > div > div > table > tbody > tr:nth-child("+str(table_num)+") > td:nth-child(3) > div > div").textprint('date:',date)# 爬取评论应用版本try:version = driver.find_element(by=By.CSS_SELECTOR, value="#commentContent > div.loading-wrap > div > div > div > table > tbody > tr:nth-child("+str(table_num)+") > td:nth-child(2) > div > div > div.comment-info.dd-flex.dd-flex-warp > span:nth-child(6)").textprint('version:',version)except:version = " "print("not found version!")time.sleep(2)try:user = driver.find_element(by=By.CSS_SELECTOR, value="#commentContent > div.loading-wrap > div > div > div > table > tbody > tr:nth-child("+str(table_num)+") > td:nth-child(2) > div > div > div.comment-info.dd-flex.dd-flex-warp > div > a").textprint('user:',user)except:user = "anoy"print("not found user!")time.sleep(2)name = driver.find_element(by=By.CSS_SELECTOR, value=" #appinfo-content > div.container > div:nth-child(2) > div.content-side > div.container-head > div.dd-flex-1.dd-flex.dd-flex-column.dd-flex-space.dd-overflow-hidden > div.logo-wrap > div.max-width-80 > div.app-name > h1").textprint('name:',name)data = [date,user,content,score,version,name]print(data)sql = 'insert into database_comments_'+str(appname) +'(date,user,content,score,version,name) values(%s,%s,%s,%s,%s,%s);'cursor.execute(sql,data)     # 插入数据db.commit() # 提交sql语句cursor.close() db.close()  # 关闭数据库连接driver.quit() # 退出浏览器

下面是调用部分,以某第三方数据网的vivo商店评论为例:

# all.py文件
import diandian
# 爬取第三方数据网蓝厂商店的下面几个应用评论数据
vivo_urls={'Outlook':'jn79t9ueolpbqy3','Office':'3403tku16vp5t14','Edge':'rn6vtpukqjzvhw4',}diandian.myscrapy(vivo_urls,4,'vivo')

2. 定时任务 sched库

参考链接:Python事件调度器定时任务sched

  1. 利用内置模块 sched 实现定时任务
    sched 模块实现了一个通用事件调度器,在调度器类中使用一个延迟函数,等待特定的时间,执行任务。但该方法会阻塞线程,直到所有被调度的任务都执行完成。

  2. class sched.scheduler(timefunc, delayfunc) 这个类定义了调度事件的通用接口,需要外部传入两个参数,
    timefunc:无参数,返回时间戳的函数。常用的有time模块里面的 time。
    delayfunc :需要一个参数,与timefunc的输出兼容,常用的有time模块的 sleep。

    '''
    初始化scheduler类对象
    time.time 返回时间戳
    time.sleep 在定时未到达之前阻塞
    用time模块的这两个函数来实例化scheduler对象
    '''
    schedule = sched.scheduler(time.time, time.sleep)
    
  3. scheduler 对象主要方法:

    1. enter(delay, priority, action, argument),延迟 delay 个时间单位安排一个事件。
    2. cancel(event):从队列中删除事件。如果事件不是当前队列中的事件,则该方法将抛出一个 ValueError。
    3. run():运行所有预定的事件。这个函数将等待(使用delayfunc() 函数),然后执行事件,直到不再有预定的事件。

代码示例:

import sched # 定时任务模块
import time # 时间模块
import datetime # 日期时间模块s = sched.scheduler(time.time, time.sleep) # 实例化scheduler对象def print_time(a='default'): # 要调用的函数print("From print_time", time.time(), a)def print_some_times():print(time.time())s.enter(10, 1, print_time) # 加入队列s.enter(5, 2, print_time, argument=('positional',))# 加入队列s.enter(5, 1, print_time, kwargs={'a': 'keyword'})# 加入队列print(s.queue)s.run()print(time.time())print_some_times()
# 1607676900.9483116
# From print_time 1607676905.9483757 keyword
# From print_time 1607676905.9483757 positional
# From print_time 1607676910.9485233 default
# 1607676910.9485233

3. django后端框架 版本3.2.5

参考链接:
菜鸟教程-django
Django官方教程 (推荐)

3.1 安装Django

  1. 使用pip install Django==x.x,安装自己需要的版本
  2. 测试是否可用:
    import django
    print(django.get_version()) # 如果可用的话会打印出版本号,我这里是3.2.5
    
  3. 创建Django项目:
    django-admin startproject mysite # mysite是项目名称。(这句是示例,后面图中我实际创建的项目名是django_app)
    


我们主要修改urls.pysettings.py文件

3.2 数据库

  1. 先设置好本地服务器环境,我使用的是phpstudy pro,启动mysql服务

    使用上图中右上角的数据库工具——SQL_Front,新建一个数据库,数据库名为comments

  2. 修改Django项目settings.py中数据库部分:

    上图中NAME是数据库名,USER是数据库用户名,PASSWORD是数据库密码

  3. 使用 python manage.py startapp database新建一个app,名字叫database,用于数据库操作。
    进入database目录,修改models.py,如下图设置好数据表类:

  4. 然后修改settings.pyINSTALLED_APPS,添加上面新建的app,也就是database,如下图所示:

  5. 使用python manage.py makemigrations databasepython manage.py migrate database对该数据表进行初始化,也就是创建这些表

    1. makemigrations的官方解释如下:

    2. migrate命令的官方解释如下:

    3. 运行上面两个命令之后,使用phpstudy pro的SQL_Front查看数据库,可以看到已经创建了我们刚才在model.py里定义的数据表

    总之,模型更改的三步指南:
    1. 在models.py中更改模型。
    2. 运行python manage.py makemigrations app名字,存储这些更改。
    3. 运行python manage.py migrate,将这些更改应用到数据库。

  6. 修改views.py,编写返回数据表内容的函数

    get_360实现了以json格式返回Comments_360表中的所有数据

  7. 修改urls.py,也就是网站目录。

    在终端输入python manage.py runserver回车,运行django项目,实现了在http://127.0.0.1:8000/360/中返回数据库中数据,如下图所示:

至此,后端部分完成。


4. 将后端部署到腾讯云和阿里云服务器上,进行生产环境部署

参考链接:【Django】宝塔面板部署Django+MySQL项目实战 这篇文章写的很详细,可以直接去看这篇文章

  1. 部署前准备

    1. 调开发模式为生产模式
      Django配置文件settings.py修改,调开发模式为生产模式:

      DEBUG = False  # 开发模式为True,上线时设置为False
      ALLOWED_HOSTS = ['8.130.98.214']  # 开发模式为*,实际生产为真实IP或域名
      STATIC_URL = '/static/' #上线模式
      # STATICFILES_DIRS = [
      #     os.path.join(BASE_DIR, "static"),    # 开发模式
      # ]
      STATIC_ROOT = os.path.join(BASE_DIR, "static")    # 生产模式
      
    2. 导出项目依赖包
      pip freeze > requirements.txt
    3. 收集静态文件
      python manage.py collectstatic # 必须调到生产模式才能成功
      其中带有后台的项目必须要收集静态文件,部署时才能显示后台。
  2. 登录腾讯云控制台,设置云服务器系统,我这里选择的系统是腾讯云专享版宝塔Linux面板

  3. 登录宝塔面板,软件商店 — 下载安装MySQL、Nginx、Python项目管理器;在Python项目管理器中安装Python 3.8

  4. 添加站点

  5. 上传本地项目至站点文件夹下

  6. 编辑uwsgi.ini文件

  7. 配置数据库,修改项目配置文件 settings.py 中 MySQL配置

  8. Python项目管理器添加项目

  9. 配置网站的配置文件

【项目整理】安卓应用商店评论监控平台相关推荐

  1. CAT - 监控平台之装配篇

    一.CAT (Central Application Tracking) 简介: CAT 是大众点评开源的一套基于java的实时应用监控平台,主要应用于服务中间件框架(MVC 框架.RPC 框架.持久 ...

  2. 建设DevOps统一运维监控平台,全面的系统监控你做好了吗?

    本文转自微信号EAWorld.扫描下方二维码,关注成功后,回复"普元方法+",将会获得热门课堂免费学习机会! 前言 随着Devops.云计算.微服务.容器等理念的逐步落地和大力发展 ...

  3. 大数据实战项目------中国移动运营分析实时监控平台 || 项目需求实现(文章最后有数据文件)

    1.业务概况(显示总订单量.订单成功量.总金额.花费时间) 2.业务详细概述(每小时的充值订单量.每小时的充值成功订单量) 3.业务质量(每个省份的充值成功订单量) 4.实时统计每分钟的充值金额和订单 ...

  4. 隧道凿岩机器人传感器_【谷企动态】天创电子管廊综合监控平台及机器人系统在国家电网项目顺利交付应用...

    天创管廊综合监控平台 及机器人系统 在国家电网项目顺利交付应用 1 项目背景 随着电缆在城市电网的广泛应用,电力隧道成为电缆敷设的主要通道之一.由于城市建设的复杂性和线路走廊资源的紧缺,电力隧道内部的 ...

  5. 使用 Android NDK 的交叉编译工具链移植 C/C++ 项目到安卓平台

    什么是 NDK? Android NDK 是一套可以让开发者在安卓应用开发中使用 C/C++ 实现特定模块的工具集,不是所有应用都需要用到,但是正确地使用可以有效提高应用运行效率和安全性. 为什么要在 ...

  6. 大数据实战项目------中国移动运营分析实时监控平台 || 项目背景

    中国移动运营分析实时监控平台 项目背景 中国移动公司旗下拥有很多的子机构,基本可以按照省份划分. 而各省份旗下的充值机构也非常的多. 目前要想获取整个平台的充值情况,需要先以省为单元,进行省份旗下的机 ...

  7. 部署Zabbix监控平台,配置及使用Zabbix监控系统,自定义Zabbix监控项目

    案例1:常用系统监控命令 案例2:部署Zabbix监控平台 案例3:配置及使用Zabbix监控系统 案例4:自定义Zabbix监控项目 1 案例1:常用系统监控命令 1.1 问题 本案例要求熟悉查看L ...

  8. 安卓应用商店上架 App 各流行开放平台地址

    安卓应用商店上架 App 各开放平台注册地址 华为开放市场 https://dwz.cn/dV6ymKLM 小米开放市场 https://cn.account.xiaomi.com/pass/regi ...

  9. 从0到1搭建前端监控平台,面试必备的亮点项目

    前言 常常会苦恼,平常做的项目很普通,没啥亮点:面试中也经常会被问到:做过哪些亮点项目吗? 前端监控就是一个很有亮点的项目,各个大厂都有自己的内部实现,没有监控的项目好比是在裸奔 文章分成以下六部分来 ...

最新文章

  1. zookeeper 集群安装
  2. 独家 | 手把手教你用R语言做回归后的残差分析(附代码)
  3. python self的含义
  4. oracle中的null 字段,Oracle下的NULL字段
  5. 手把手教会你(单/多)文件上传(并修改文件默认的最大最小值)
  6. YGC问题排查,又让我涨姿势了!
  7. vue 引入qunee_Vue页面中js引入的问题
  8. C++基于STL的演讲比赛流程管理系统
  9. springboot整合freemarker中文乱码
  10. 第二季-专题0-课程规划
  11. Effective C++(6) 如何拒绝编译器的自动生成函数
  12. BroadCastReceive的理解和使用
  13. python月份字符串_python实现字符串和日期相互转换的方法
  14. stata 将数据集变量名称导出_Stata 15 统计数据分析软件
  15. 基于STM32F405平台的多摩川协议编码器通讯过程(1)
  16. ios下使用speex进行音频压缩
  17. Android 百度地图定位显示当前位置
  18. 2020年阴历二月二十八 投资理财~如何正确面对黑天鹅
  19. 计算机网络谢希仁第七版课后习题答案(第九章)
  20. 从女孩儿手中音乐般滑落

热门文章

  1. android 拦截耳机按键,Android耳机监测以及耳机按键监测
  2. java求亲密数,怎么写更好更快?
  3. 图形工作站安装win7+ubuntu双系统
  4. 三维高清vR展示模型的应用及优势
  5. win10浏览器闪退_Win10 Build 14942 Edge 浏览器闪退怎么解决?
  6. flex布局,没有justify-self,如何实现一左一中布局
  7. 2022年有高级软考职称可以入深户吗?
  8. EfficientNet B0 训练 Standford 汽车图片分类(对比ResNet34)
  9. 沐风:企业网络营销赚钱关键设计
  10. 解决:CondaHTTPError: HTTP 000 CONNECTION FAILED for url <https://repo.anaconda.com/pk gs/main/win-64/c