在简单学习了Pyppeteer之后,就想利用其来实现一个爬取实战来巩固知识,也是为了做点东西,让学的东西不那么空洞。

然后选取了微博评论区进行爬取。

但是在复制网页端的微博的节点的Selector并进行查找的时候,发现怎么都找不到。(这个问题我暂时也不知道什么情况)

于是,在这种情况下,我选择了移动端的微博,(好像确实要容易爬取一些)

以下是我在写程序时记录的一些问题及解决吧(应该算日志吧):

   """思路:先进入wb网页,然后利用选择器点击每个动态下面的评论,接着获取查看全部评论的href,然后拼凑成新的url,进入动态的详情页,然后爬取里面的评论。爬取评论包含:用户名,评论内容,ip地址然后在分别把所有评论用逗号分隔,拼凑成一个文本,进行文本词频统计生成词云,用AG图片作为词云形状同理对用户名和ip地址进行操作  - 3.14
""""""-3.16
问题:solved-1.网页版的微博在爬取的时候,使用复制过来的Selector会报错,显示找不到节点,没有找到解决方案,于是转向爬取移动端的微博网页.solved-2. click函数如何使用才会跳转。unsolved-3. click在使用该函数之后并没有在显示的界面上跳转,还需要手动点击一下,函数才开始运行,暂未得到解决. ####################(还未解决)   ------> solved : 换选择器,点微博正文也能跳转(3.20)solved-4. 在跳转到动态的详情页之后,如何让网页往下滑成了新的问题.在大量搜索后仍然没有找到解决方案,然后寻求Pyppeteer的API,发现里面也没有对应的方法可以使用,最后想到了可以通过键盘的PageDown键来进行下滑操作.但这样做有缺点,首先就是不知道要获取全部评论要按多少次PageDown键,其次是这样做好像有一点耗时。solved-5. 但是在下滑时,如果滑到新评论,需要进行登录,本来想要使用模拟登录来解决该问题,然后想起来pyppeter的launch里面有可以记录登录状态的参数,于是先模拟一次打开界面,然后停留一段时间进行登录,从而使得登录状态的数据被保存下来。在后面的下滑网页的操作中不再需要操作。to-be-solved-6. 在获取评论信息并分类时,发现存在一些数组越界问题,于是采用“列表推导 if else”的结构来解决这种情况。同时对于没有获取到的评论,使用"暂无"来代替,这在后面进行词频统计的时候要剔除掉该词。########################(需要解决)  ---------> solved: 通过查看网页结构发现,在评论出现表情或者图片的时候,评论内容会在标签h3下面在延伸.解决方法就是用户名和评论内容分别获取,一个用h4标签, 一个用h3标签。
Now: 1.现在已经可以爬取一个动态里面的部分评论,并进行分类存储在一个字典里面,仍需储存在一个文件里面。  -> solved(3.20)2.现在还需要事先获取每条动态的评论数,从而得到每次下滑网页按键的次数。               -> solved(3.20)3.还需要设置动态页的按键次数,从而获取更多的动态                                 ->solved(3.20)4.还需要能够爬取多条动态。                                                  ->solved(3.20)5.现在使用BASIC_URL_2,SELECTOR_BASIC_2
函数(现有):1.初始化2.爬取URL3.点击评论进入详情页4.解析详情页评论信息3.20:5. 保存数据到文件里面6. 获取更多动态7. 获取文件内容并进行分词后的结果8. 设置屏幕尺寸为全屏更新思路:路:先进入wb网页,然后利用选择器点击每个动态下面的评论按钮,进入动态的详情页,不断下滑获取更多评论,然后爬取里面的评论。同时网页也需要下滑操作来获取更多的动态。爬取评论包含:用户名,评论内容,ip地址然后在分别把所有评论用逗号分隔,拼凑成一个文本,进行文本词频统计生成词云,用AG图片作为词云形状同理对用户名和ip地址进行操作  - 3.16
""""""-3.20
日志更新库:1. logging2. 在经过初始化设置后,用logging.info输出的信息带有时间,可以把logging.info当成一个print来用3. 初始化设置:logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s : %(message)s')
中文分词库:1. jieba词云设置:
# w=wordcloud.WordCloud(font_path='msyh.ttc',width=800,height=600,max_words=150,font_step=2,stopwords=stopwords,collocations=False)1. font_path :表示字体路径,可以从C->Windows->Fonts 获取。2. width: 输出画布的宽度3. height: 输出画布的高度4. max_words: 画布里面显示词数的最大数5. font_path: 字体步长6. stopwords: 停用词,表示需要屏蔽的词,在这里用了中文的停用词,防止一些特殊符号影响输出。7. collocations: 将参数设置为False,防止关键词出现重复的现象。
词云常规函数:1. w.generate(txt)  #向 WordCloud 对象 w 中加载文本 txt2. w.to_file(PNG_PATH.format(str=FIlE_NAME[i]))   # 将词云输出为图像文件 .jpg或.png文件
"""

下面是源代码:

import logging
import tkinter
from pyppeteer.errors import TimeoutError
from wordcloud import WordCloud
import asyncio
from pyppeteer import launch
from pyquery import PyQuery as pq# 词频统计
import jieba
import wordcloud
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s : %(message)s')
TIMEOUT = 10
DOWN_NUMBER = 260  # 动态页按下的次数
BEGIN_NUMBER = 4    # 开始动态的index
END_NUMBER = 50     # 结束动态的index
FILE_PATH = "./KPL-COMMENT/{str}.txt"  # 保存文件路径
PNG_PATH = "./KPL-COMMENT/{str}.png"
FIlE_NAME = ["comments","ip","user_names"]  # 储存三个文件名# WINDOW_WIDTH, WINDOW_HEIGHT = 1366, 768
HEADLESS = False
BASIC_URL = "https://weibo.com/agcwh"
COMMENT_URL = "https://weibo.com{comment_url}"
SELECTOR_BASIC = "#scroller > div.vue-recycle-scroller__item-wrapper > div:nth-child(1) > div > article > footer > div > div:nth-child(2) > div > span"BASIC_URL_2 = "https://m.weibo.cn/u/5878848794?uid=5878848794&t=0&luicode=10000011&lfid=100103type%3D1%26q%3Dag%E8%B6%85%E7%8E%A9%E4%BC%9A"  # 实际用到的网页链接
SELECTOR_BASIC_2 = "#app > div:nth-child(1) > div:nth-child(1) > div:nth-child({index}) > div > div > div > footer > div:nth-child(3) > h4"     #  实际用到的评论内容选择器SELECTOR_BASIC_3 ="#app > div:nth-child(1) > div:nth-child(1) > div:nth-child({index}) > div > div > div > article > div.weibo-og > div.weibo-text"     # 实际用到的点击用的选择器
#app > div:nth-child(1) > div:nth-child(1) > div:nth-child(4) > div > div > div > article > div.weibo-og > div.weibo-text
# index从4开始,这是点击评论的selector# 设置中文停用词
stopwords = set()
content = [line.strip() for line in open('stop_words.txt','r',encoding='utf-8').readlines()]
stopwords.update(content)browser, page = None, Nonedef screen_size():# 设置屏幕尺寸为全屏tk = tkinter.Tk()width = tk.winfo_screenwidth()height = tk.winfo_screenheight()tk.quit()return {'width': width, 'height': height}async def init( ):global browser, pagebrowser = await launch(headless=HEADLESS, userDataDir='./userdata', args=['--start-maximized','--disable-infobars'])#网页全屏page = await browser.newPage()await page.setViewport(screen_size())await page.evaluateOnNewDocument('Object.defineProperty(navigator,"webdriver",{get:()=>undefined})')# 隐藏WebDriver信息,防止被拦截await page.setJavaScriptEnabled(enabled=True)async def scrape(url, selector):"""爬取网页的基本操作"""logging.info("Scraping %s...", url)try:await page.goto(url)await page.waitForSelector(selector, options={'timeout':TIMEOUT * 100})except :logging.error("Error occurred while scraping %s", url, exc_info=True)async def click_comment(index):"""点击微博正文从而进入相应的详情页"""global pageselector = SELECTOR_BASIC_2.format(index=index)# await scrape(BASIC_URL_2, selector=selector)count = await get_count(selector)selector = SELECTOR_BASIC_3.format(index=index)# 这是微博正文的Selector,可以点击,但是评论的数字点不了try:await asyncio.gather(   # 先等待后跳转page.waitForNavigation(), # 等待页面跳转函数page.click(selector,options={'button':'left','delay':1}))except :logging.info("No node found for selector.....")await get_comment(count)# 复制过来的微博评论用户名的Selector
#app > div:nth-child(1) > div:nth-child(1) > div:nth-child(6) > div > div > div > footer > div:nth-child(3) > h4
# 复制过来的微博正文的Selector
#app > div:nth-child(1) > div:nth-child(1) > div:nth-child(5) > div > div > div > article > div.weibo-og > div.weibo-text
async def get_count(selector):"""获取每条动态的评论数"""# await scrape(BASIC_URL_2, selector=selector)try:await page.waitForSelector(selector, options={'timeout':TIMEOUT * 100})except TimeoutError:logging.error("Error occurred while scraping ...",  exc_info=True)doc = pq(await page.content())count = doc(selector).text()   # 获取的count为str类型print(count)if count:return int(count)else :return 260async def get_comment(count):"进入详情页之后,先利用键盘下滑,然后爬取评论数据"for i in range(count):# 把评论数乘以10作为按下ArrowDown键的次数,这样仍不能够实现完全获取全部评论的效果,但可以获取大部分# 利用键盘上的ArrowDown键,或者叫做PageDown键,来实现网页不断往下滑,不断更新内容的功能await page.keyboard.press('ArrowDown')try:    #有时会莫名其妙出一些找不到结点的问题(我也不知道为什么),用try except解决await page.waitForSelector(".comment-content ", options={'timeout':TIMEOUT * 100})except:logging.info("TimeoutError")doc = pq(await page.content())# messages = [item.text().split('\n') for item in doc(".comment-content .m-text-box ").items()] names = [item.text() for item in doc(".comment-content .m-text-box h4").items()]comments = [item.text() for item in doc(".comment-content .m-text-box h3").items()]# 由于网页结构关系,每条评论的用户名和评论内容的文本可以一块获取,所以messages数组储存每条评论的用户名和评论内容,后面再分开ips = [item.text().split() for item in doc(".comment-content .time").items()]# ip地址和发布时间的文本连在一块,这里把每条评论的发布时间和ip地址用spilt分开,以便后续储存ip地址try:comment_info={'user_names' : names,'comments':comments,'ip':[ips[i][-1][2:]  for i in range(len(ips))]# 这里面利用切片[2:] 把ip地址里面的“来自”两个字删掉 ,同时考虑了数组下标越界的情况(其实是因为在运行时存在越界情况导致出错,所以需要进行改善)}except IndexError :logging.info("ips:%s",ips)logging.info("出现数组下标越界情况,后面评论暂不爬取")# 用comment_info这样一个字典来存储获取的评论信息for i in range(3):await save_data(FIlE_NAME[i], comment_info[FIlE_NAME[i]])# logging.info(comment_info)# logging.info(len(messages))async def get_more(): #等到某动作完成"""获取更多的动态,其实质是先不断往下滑,让网页加载更多内容"""await page.goto(BASIC_URL_2)for i in range(DOWN_NUMBER):# 把评论数乘以10作为按下ArrowDown键的次数,这样仍不能够实现完全获取全部评论的效果,但可以获取大部分# 利用键盘上的ArrowDown键,或者叫做PageDown键,来实现网页不断往下滑,不断更新内容的功能await page.keyboard.press('ArrowDown')async def save_data(str, data):"""保存数据"""file_name = FILE_PATH.format(str=str)with open(file_name, "a", encoding="utf-8") as f:f.write(','.join(data))async def get_text(filename):"""获取文件中的内容,并用中文分词库进行分词后返回"""f = open(filename, "r", encoding='utf-8')txt = f.read()f.close()txt=' '.join(jieba.lcut(txt))return txtasync def main():await init()await page.goto(BASIC_URL_2)await get_more()while True :  for i in range(BEGIN_NUMBER, END_NUMBER+1):await click_comment(i)logging.info("Scraping number:%d......",i-3)# await click_comment(5)for i in range(3):txt = await get_text(FILE_PATH.format(str=FIlE_NAME[i]))logging.info("txt:%s",txt)print(type(txt))w=wordcloud.WordCloud(font_path='msyh.ttc',width=800,height=600,max_words=150,font_step=2,stopwords=stopwords,collocations=False)w.generate(txt)w.to_file(PNG_PATH.format(str=FIlE_NAME[i]))logging.info('make wordCloud successfully!')breakawait browser.close()asyncio.get_event_loop().run_until_complete(main())

运行结束就会在同级文件夹下一个KPL-COMMENT的文件夹,文件夹下面出现三个文本文件,三个图片文件。

图片效果一览:

comments.png

ip.png

user_names.png

写在最后:

爬取的时候有一点没有考虑,那就是每条评论的回复评论,这点我没有进行爬取。

由于本人确实水平有限,所以写的仍不够完善,写这篇博客只是为了记录我自己写的一个案例。当然如果对大家有帮助那是最好不过了。如果有大佬指正问题,随时欢迎喔

Pyppeteer爬取移动端微博评论区简单案例相关推荐

  1. python爬取微博评论并做词频分析_爬取李子柒微博评论并分析

    爬取李子柒微博评论并分析 微博主要分为网页端.手机端和移动端.微博网页版反爬太厉害,因此选择爬取手机端. 1 需求 爬取李子柒微博中视频的评论信息,并做词频分析. 2 方法 2.1 运行环境 运行平台 ...

  2. 爬取李子柒微博评论并分析

    爬取李子柒微博评论并分析 微博主要分为网页端.手机端和移动端.微博网页版反爬太厉害,因此选择爬取手机端. 微博手机端地址:https://m.weibo.cn 1 需求 爬取李子柒微博中视频的评论信息 ...

  3. 百度贴吧界面html程序代码,python爬虫例题:爬取百度贴吧评论区图片和视频

    百度贴吧是全球最大的中文交流平台,你是否跟我一样,有时候看到评论区的图片想下载呢?或者看到一段视频想进行下载呢? 今天,本期Python教程带大家通过搜索关键字来获取评论区的图片和视频. [二.项目目 ...

  4. 爬取b站视频评论用户信息!这些评论的才是大神!

    最近马保国老师在b站挺火的,关于他的视频播放量很高,b站视频评论区都是人才说话好听,写个爬虫爬取一下b站评论区用户信息和评论内容. 一.准备工作 1.工具 (1)Chrome 谷歌浏览器 安装地址:h ...

  5. python3网络爬虫--爬取b站视频评论用户信息(附源码)

    文章目录 一.准备工作 1.工具 二.思路 1.整体思路 2.爬虫思路 三.分析网页 1.分析网页加载方式 2.分析数据接口 3.获取oid 四.撰写爬虫 五.存储数据 六.总结 你爱我,我爱你,蜜雪 ...

  6. python爬取网易云音乐评论并进行可视化分析

    2019独角兽企业重金招聘Python工程师标准>>> 前言 今天为大家一个爬取网易云音乐评论的Python案例,并用Python的第三方库来进行可视化分析,生成图表样式,可以清晰地 ...

  7. 中国女足绝地大逆转,爬取了微博评论区,评论很精彩

    昨晚,女足16年后重夺亚洲杯,决赛落后两球,依然能保持对比赛的观察和思考,下半场从容调度人手,最后完成逆转. 打开微博一看,WC,微博推给我的第一条就是一篇瓜文. 这几天正好有的瓜,于是就爬了一下微博 ...

  8. 爬取了 36141 条评论数据,解读 9.5 分的《海王》是否值得一看

    这是第一个python项目,之前看到了<爬取了 48048 条评论数据,解读 9.3 分的<毒液>是否值得一看?>这篇文章,一直想自己动手做一个,刚刚好前两天看了<海王& ...

  9. 简单的爬取B站视频评论

    2019年12月20日15:14:09补充: 这篇博客为刚学爬虫的一个简单实践,主要使用到的为selenium模拟点击 补充说明的主要原因是有小伙伴问我评论提取的相关问题,这里统一回复一下 最简单的办 ...

最新文章

  1. Wiki动画回顾系列序目录
  2. LeetCode Best Time to Buy and Sell Stock with Cooldown(动态规划)
  3. sdwan支持的网络设备类型
  4. 淮海工学院linux实验报告三,作业三 实验报告
  5. 02基于python玩转人工智能最火框架之TensorFlow人工智能深度学习介绍
  6. 关于iOS里的做动画方法的差别与注意事项
  7. es中的一些知识点记录
  8. 软帝java培训实习日志,在软帝学习的第一个星期的小总结
  9. Excel度分秒转度--公式大解析
  10. 类似微信的即时通讯服务器,除了微信,还有这些常用即时通讯APP
  11. 【OS笔记 4】操作系统的组织结构(层次结构、微内核结构)虚拟机的概念
  12. 维生素D与肠道菌群的互作
  13. 详解去中心化代币发行机制IDO:七大平台的特性与现状 |链捕手
  14. E. Xenon's Attack on the Gangs,Codeforces Round #614 (Div. 2),树形dp
  15. java计算机毕业设计移动垃圾分类车管理平台源码+系统+mysql数据库+lw文档
  16. 【问题解决】samba添加用户和密码时报错 Failed to add entry for user
  17. 深入学习SpringMVC框架
  18. HTTP (RESTful) API 响应时间分析及SLA定义
  19. 解密openGauss DB4AI框架的内部机理
  20. 刷题_25:星际密码 and 数根

热门文章

  1. 腾讯企鹅号联合新榜发布内容创作版权保护行业报告
  2. methods的使用
  3. The import java.io cannot be resolved (类库无法解析的问题解决 )
  4. android手机闪退原因
  5. Tigress学习系列【1】(安装与排错)
  6. java arrays.sort原理_Arrays.sort()原理
  7. 技术分享 | 使用 sync_diff_inspector 对两个 MySQL 进行数据校验
  8. css边框角;table 合并单元格
  9. MT6739 PDAF移植
  10. 机械师F117毒药 评测怎么样