ADB命令来捕获设备屏幕和发送鼠标事件来实现抓取公众号文章
现在公众号需要登陆账号才能看到评论内容。登陆要账号的密码等,token还会过期。
现在的很多小程序进行了加密,那是否有方案可以抓取小程序或公众号的数据呢?
解决方案:
1.通过ADB命令来捕获设备屏幕快照,传递给电脑并且保存在本地文件;
2.通过百度飞桨ocr解析图片获取内容并保存;
3.根据解析的内容和坐标,向手机发送鼠标事件(点击和上下,左右滑动)来控制页面的跳转。
有待解决的问题:
百度飞桨ocr解析普通文字正确很高,但是经常把图片图标或logo识别成不同的文字,导致解析不错误。
由于公众号文章形式多样,很难统一处理,经常需要调整算法。
当然爬取普通单一样式的文章不在话下。
具体解决方案是:
开一个协程专门进行手机抓屏幕保存到电脑。
另开一个协程进行图片解析数据保存,根据解析的内容发送鼠标事件控制手机中的应用打开和翻到对应页面。
注意:
1.需要一个通过数据线连接电脑的安卓手机(苹果手机不行,不能是充电线,要是数据线,有的线只有充电功能无数据传输功能)。
2.翻页不能太快,因为ocr解析图片很慢,翻页太快会漏掉部分屏幕的解析。
3.因为公众号有记忆功能。如上次看文章翻到底部,下次再点进来看到的文章仍在底部。当下拉三次ocr识别页面相同就认为到顶,当上拉三次ocr识别的页面相同就认为到底部。
是不是很强大,把软件的加密算法变成了花瓶,达到所见即所得。这就是AI的强大应用之一,妥妥的非主流。
来分享部分抓公众号文章及评论的代码:
主程序:
async def main():
print("main")
sno = 0
singleton1 = OCSingleton()
img_path = r"screenshot.png"
file_to_open = Path(img_path)
if (file_to_open.is_file()):
os.remove(img_path)
isDawAdbScreenshot = True
if(isDawAdbScreenshot):
# 初始化Pygame
pygame.init()
ocr = PaddleOCR(use_angle_cls=True, lang="ch", use_gpu=False)
try:
await taskProccess(isDawAdbScreenshot, singleton1, ocr)
except Exception as e:
print('Exception:', e)
await taskProccess(isDawAdbScreenshot, singleton1, ocr)
finally:
print('finally...')
主要的事务处理(发送鼠标事件,起协程,页面跳转控制):
async def taskProccess(isDawAdbScreenshot, singleton1, ocr):
print("main 点击坐标判断0-0")
# sn = 0
while True:
task1 = asyncio.create_task(adbPngGrap( isDawAdbScreenshot)) # 使用asyncio.create_task将函数打包成一个任务,该协程将自动排入日程等待运行
task2 = asyncio.create_task(check_text_show(not isDawAdbScreenshot, ocr))
if(checkNotSkip(singleton1, True)):
await asyncio.sleep(4)
await task1
result1 = await task2
# print(sno) # 等待 task1 如果task1中存在耗时操作,则挂起
print(result1)
# print("main 点击坐标判断:%d ; %d" %(len(result1), (result1[0] == ['home'])))
print("main 点击坐标判断0 now:%s, singleton1.sameArticleTime:%d, singleton1.isArticleTop:%d, singleton1.pageName:%s, singleton1.isNotCommonArticle:%d,singleton1.isFinishSingleArticle:%d, singleton1.backPageBox:%s, singleton1.secondBackPageBox:%s" %(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), singleton1.sameArticleTime, singleton1.isArticleTop, singleton1.pageName, singleton1.isNotCommonArticle ,singleton1.isFinishSingleArticle, singleton1.backPageBox, singleton1.secondBackPageBox))
if((singleton1.pageName == '当前文章') and (not singleton1.isArticleTop) and (singleton1.down_times != 50) and (singleton1.down_times > 0)):
singleton1.down_times = singleton1.down_times-1
swipe_cmd = "adb shell input swipe {} {} {} {} {}".format(