当前位置: 首页 > news >正文

爬虫逆向--Day12--DrissionPage案例分析【小某书评价数据某东评价数据】

案例一:搜索【美妆】获取每一个卡片的信

 代码如下:

# 导入时间等待库
import time
# 导入ChromiumPage
from DrissionPage import ChromiumPage
# 数据写入到excel文件
from DataRecorder import Recorder# 写入到excel表格中
recorder = Recorder("./data.xlsx")
recorder.set.show_msg(False)  # 不显示日志信息--会显示很多无用的日志,所以这里屏蔽掉无用的日志打印# 6--【数据解析函数】
def find_first_key_value(data, target_key):# (1) 处理数据为字典的递归遍历if isinstance(data, dict):  # 判断是否是字典类型# 便利字典的key和valuefor key, val in data.items():# 如果key等于传递进来的target_key,就把对应的value返回出去if key == target_key:return val# 递归遍历子元素ret = find_first_key_value(val, target_key)if ret is not None:return ret# (2) 处理数据为列表的递归遍历if isinstance(data, list):for item in data:  # 遍历列表获取列表中的字典形式的列表元素# 根据target_key提取对应的value值ret = find_first_key_value(item, target_key)if ret is not None:return retreturn Nonedef handler(page, keyword):# 访问小红书的搜索【美妆】后的界面链接# https://www.xiaohongshu.com/search_result?keyword=美妆&source=web_explore_feedpage.get(f"https://www.xiaohongshu.com/search_result?keyword={keyword}&source=web_explore_feed&type=51")time.sleep(5)  # 为了防止网络的影响加载慢,可以等待5秒,让数据加载一下# 7--【循环进行向下滑动滚轮,不断加载跟多内容】for i in range(1, 3):   # 滚轮向下滑动3次    滚动的操作会做3次# 为了捕获失败,防止程序报错,加上try...excepttry:# 通过class="note-item" 定位界面上的每一个卡片数据# cards = page.eles('@class=note-item')  # 该行代码等价于下一行,都是class定位cards = page.eles('.note-item')# 3--【(1) 启动监听机制  监听卡片详情接口   对指定的数据包进行监听】page.listen.start("/sns/web/v1/feed")# 遍历的每一个卡片for card in cards:# print(card)# 通过局部定位定位大图,根据标签名定位img标签,并进行点击操作card.ele('@tag()=img').click(by_js=True)  # by_js=True 参数可以不写,进行默认# 4--【(2) 等待卡片详情接口数据返回  点击显示的数据是动态请求的】res = page.listen.wait(count=1, timeout=1, fit_count=True)# (3) 获取数据data = res.response.bodyprint("data:::", data)time.sleep(2)#  数据提取nickname = find_first_key_value(data, "nickname")title = find_first_key_value(data, "title")desc = find_first_key_value(data, "desc")comment_count = find_first_key_value(data, "comment_count")liked_count = find_first_key_value(data, "liked_count")# 基于recorder将采集的数据写入excel,recorder需要是字典格式# 把每个字典作为是一行数据,一行一行写入,所以这里需要组装成字典格式map = {"博主昵称": nickname,"标题": title,"详情": desc,"评论数": comment_count,"点赞数": liked_count,}recorder.add_data(map)recorder.record()# 5--【关闭卡片并等待  弹窗关闭】close_btn = page.ele('@class=close close-mask-dark')close_btn.click()time.sleep(2)except Exception as e:print("错误失败了--error::::", e)finally:# 7.1--【滚动滚轮】   try抛不抛异常,这个finally都会在try执行完一次以后被执行一次page.scroll.up(100)  # 点击滑块time.sleep(1)page.scroll.to_bottom()time.sleep(1)def main():with open("关键词.txt", mode="r", encoding="utf-8") as f:# 1--【readlines 逐行进行读取txt文件中的搜索关键词,并以列表的形式进行返回】keyword_list = f.readlines()# 创建浏览器驱动对象page = ChromiumPage()# 访问小红书首页page.get("https://www.xiaohongshu.com/explore")# 2--【小红书的登录很难,如果用逆向的话比较麻烦,所以这里我们进行手动登录】input("等待登录")for keyword in keyword_list:# 把显示的页面page和关键词keyword传递过去handler(page, keyword)# 程序的入口
main()"""对代码中【】括起来的注释进行分析和解释1、在编写代码前需要创建一个【关键词.txt】文件,里面存放将要搜索的关键词,例如:美妆、生活2、因为小红书的登录如果使用逆向操作比较麻烦,所以我们可以使用ChromiumPage控制浏览器,进行手动扫码登录3、因为卡片点击后,每次放大显示的数据都是通过接口直接请求的数据,所以我们需要监听,每次请求后接口返回的数据因为如果通过逆向发送请求,并且获取接口的返回数据比较麻烦(接口中的参数和返回的数据都进行了加密处理还需要破解)所以我们可以通过page提供的监听机制,可以动态的获取被监听的接口的请求和返回的数据3.1、监听不能放到for循环里面,不然每点击一次卡片数据都会开启一次监听,所以需要放到外面,开启一次监听即可4、获取监听到指定请求响应回来的数据内容  count=1, timeout=1, fit_count=True 参数可写可不写5、点击放到后,需要先关闭放大后的弹窗,才能继续进行下一个点击,不然就只能获取到一个卡片数据6、数据解析方法有案例7、因为每一页只能显示几条数据,所以我们需要滑动滑块加载更多因为当try...except加载完以后,不管会不会抛异常,都会执行finally中的代码,所以我们把点击滑块,滑动滑块的动作放到这里问题1:不能滚轮滚到底在进行加载数据吗?不能,因为每次滚轮滚到底,加载完以后,滚轮自动就会回到中间问题2:滚轮可以一下滚到底,在一个一个点吗?因为滚轮滚到底以后,会在动态在加载数据,滚轮还会回到中间,在往下滚,在回到中间,类似一页一页的7.1、100就是点击的时候上下晃动100个像素,不要这个也行直接滑倒底部  写50 100 200都可以 为了模拟人的行为 up是向上100个像素再往下滑倒底部,更真实的模拟人的行为"""

准备文件1:创建一个txt文件,用于存放需要搜索的字段,比如需要获取"美妆"和"生活"的数据,就写"美妆"和"生活"

 分析一:当代码打印【等待登录】的时候就需要我们手动扫描登录,减少了逆向破解的繁琐操作

 分析二:

 分析三:

1、通过class="note-item" 定位界面上的每一个卡片数据,

2、通过局部定位定位大图,根据标签名定位img标签,并进行点击操作

分析四:

 分析五:

for i in range(1, 3):try:print("开始执行-----try")except Exception as e:print("开始执行-----try", e)finally:print("滚轮滑动了一次")"""开始执行-----try滚轮滑动了一次开始执行-----try滚轮滑动了一次
"""

分析六:

dic = {'a': {'b': 'i am b','c': 'i am c','d1': {'d1': 'i am d1'}},'ab': {'abb': 'i am abb'},'cc': [{'c1': 'i am c1', 'c2': 'i am c2'}]
}# 数据解析函数
def find_first_key_value(data, target_key):# (1) 处理数据为字典的递归遍历if isinstance(data, dict):  # 判断是否是字典类型# 便利字典的key和valuefor key, val in data.items():# 如果key等于传递进来的target_key,就把对应的value返回出去if key == target_key:return val# 递归遍历子元素ret = find_first_key_value(val, target_key)if ret is not None:return ret# (2) 处理数据为列表的递归遍历if isinstance(data, list):for item in data:  # 遍历列表获取列表中的字典形式的列表元素# 根据target_key提取对应的value值ret = find_first_key_value(item, target_key)if ret is not None:return retreturn None# 把json类型的数据转递作为第一个参数传递进去,把需要获取数据的key作为第二个参数,
# 就可返回得到key对应的value
ret_a = find_first_key_value(dic, "a")
print(ret_a)
# {'b': 'i am b', 'c': 'i am c', 'd1': {'d1': 'i am d1'}}ret_d1 = find_first_key_value(dic, "d1")
print(ret_d1)
# {'d1': 'i am d1'}ret_abb = find_first_key_value(dic, "abb")
print(ret_abb)
# i am abbret_c = find_first_key_value(dic, "c")
print(ret_c)
# i am cret_c2 = find_first_key_value(dic, "c2")
print(ret_c2)
# i am c2

分析七:爬取的结果如下

案例二:爬取某东某个商品的【全部评价】数据信息

import json
# 导入时间等待库
import time
# 导入ChromiumPage
from DrissionPage import ChromiumPage
# 数据写入到excel文件
from DataRecorder import Recorderrecorder = Recorder("JD.xlsx")
recorder.set.show_msg(False)def find_key_val(data, target_key, max_count=1):results = []# (1) json字符串反序列化  先判断传递来的是字符串吗?是的话就反序列化转化为对象if isinstance(data, str):try:data = json.loads(data)except json.JSONDecodeError:return resultsdef _search(data):# 最大数量限制if len(results) == max_count:return# 处理数据为字典的递归遍历if isinstance(data, dict):for key, val in data.items():if key == target_key:results.append(val)if len(results) == max_count:return# 递归遍历子元素_search(val)# (2) 处理数据为列表的递归遍历if isinstance(data, list):for item in data:ret = _search(item)if ret is not None:return retreturn None_search(data)return resultsdef handler(page):try:# 监听某个固定的接口page.listen.start("client.action")# 定位到”全部评价“这个按钮,并点击page.ele('@text()=全部评价').click()# 因为在滚动滚轮的时候被监听的接口会不断的更新返回的数据,# 所以我们要写死循环不断的接听返回的数据,不然监听的数据只会返回一条评价while 1:# 获取返回的数据 循环一次,获取一次评价数据res = page.listen.wait()data = res.response.bodyprint("data:::", data)# 解析数据commentInfoList = find_key_val(data, "commentInfo", 11)for commentInfo in commentInfoList:map = {"用户名": commentInfo.get("userNickName"),"评论时间": commentInfo.get("commentDate"),"评论内容": commentInfo.get("commentData"),"评分": commentInfo.get("commentScore"),}recorder.add_data(map)recorder.record()# 滚动滚轮并等待page.ele('@class=_rateListContainer_1ygkr_45').scroll.to_bottom()time.sleep(3)  # 防止被封号except Exception as e:print("错误失败了---error:::", e)def main():# 创建浏览器驱动对象page = ChromiumPage()# 访问需要爬取的商品的链接page.get("https://item.jd.com/100146260385.html")input("等待登录")handler(page)# 程序的入口
main()"""在Python中,字符串序列化是将数据结构(如字典、列表等)转换为字符串格式的过程,而反序列化则是将字符串重新转换回原始数据结构‌。以下是主要实现方式:json模块‌(最常用):json.dumps()实现序列化,可将Python对象转为JSON格式字符串‌json.loads()实现反序列化,将JSON字符串转回Python对象‌处理中文时建议添加ensure_ascii=False参数避免Unicode编码‌import jsondata = {"name": "张三", "age": 25}# 序列化json_str = json.dumps(data, ensure_ascii=False)  # 反序列化 restored_data = json.loads(json_str)"""

分析一:如果给出的返回数据是字符串格式的,就需要先进行反序列化操作

import jsondic = {'a': {'b': 'i am b','c': 'i am c','d1': {'d1': 'i am d1'}},'ab': {'abb': 'i am abb'},'data': [{'commentInfo': {'name': 'i am name_1', 'userImgURL': 'i am userImgURL_1', 'iconType': 'i am iconType_1'}},{'commentInfo': {'name': 'i am name_2', 'userImgURL': 'i am userImgURL_2', 'iconType': 'i am iconType_2'}},{'commentInfo': {'name': 'i am name_3', 'userImgURL': 'i am userImgURL_3', 'iconType': 'i am iconType_3'}}]
}json_str = json.dumps(dic, ensure_ascii=False, indent=4)
# print(type(json_str))
# print("json_str:", json_str)def find_key_val(data, target_key, max_count=1):results = []# (1) json字符串反序列化  先判断传递来的是字符串吗?是的话就反序列化转化为对象if isinstance(data, str):try:data = json.loads(data)print("进行了反序列化")except json.JSONDecodeError:return resultsdef _search(data):# 最大数量限制if len(results) == max_count:return# 处理数据为字典的递归遍历if isinstance(data, dict):for key, val in data.items():if key == target_key:results.append(val)if len(results) == max_count:return# 递归遍历子元素_search(val)# (2) 处理数据为列表的递归遍历if isinstance(data, list):for item in data:ret = _search(item)if ret is not None:return retreturn None_search(data)return resultsret_c2 = find_key_val(json_str, "commentInfo")
print(ret_c2)
"""进行了反序列化[{'name': 'i am name_1', 'userImgURL': 'i am userImgURL_1', 'iconType': 'i am iconType_1'}]
"""

分析二:定位到”全部评价“这个按钮

http://www.dtcms.com/a/296806.html

相关文章:

  • MySQL零基础教程增删改查实战
  • java后端
  • mujoco playground
  • DBA常用数据库查询语句
  • DevOps 完整实现指南:从理论到实践
  • 论文阅读:《Many-Objective Evolutionary Algorithms: A Survey. 》多目标优化问题的优化目标评估的相关内容介绍
  • Android LiveData 全面解析:原理、使用与最佳实践
  • Rust生态中的LLM实践全解析
  • 【C# 找最大值、最小值和平均值及大于个数和值】2022-9-23
  • 项目质量如何提升?
  • 教育培训系统源码如何赋能企业培训学习?功能设计与私有化部署实战
  • 使用 Vue 实现移动端视频录制与自动截图功能
  • MySQL---索引、事务
  • Docker 打包Vue3项目镜像
  • 互联网广告中的Header Bidding与瀑布流的解析与比较
  • 性能测试-groovy语言1
  • 使用 LLaMA 3 8B 微调一个 Reward Model:从入门到实践
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-19,(知识点:PCB布局布线的设计要点)
  • 类和包的可见性
  • 勾芡 3 步诀:家庭挂汁不翻车
  • Spring Data JPA 中的一个注解NoRepositoryBean
  • Edwards爱德华干泵报警信息表适用于iXH, iXL, iXS, iHand pXH
  • 机器学习的基础知识
  • istio tcp连接超时测试
  • android 小bug :文件冲突的问题
  • Linux 磁盘挂载,查看uuid
  • vlm MiniCPM 学习部署实战
  • 上证50ETF期权的交易时间是什么时候?
  • 洛谷 P2572 [SCOI2010] 序列操作 题解(线段树)
  • 高可用架构模式——如何应对接口级的故障