惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
AWS News Blog
AWS News Blog
Google DeepMind News
Google DeepMind News
U
Unit 42
博客园 - 叶小钗
博客园 - 聂微东
GbyAI
GbyAI
Stack Overflow Blog
Stack Overflow Blog
有赞技术团队
有赞技术团队
aimingoo的专栏
aimingoo的专栏
D
DataBreaches.Net
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Jina AI
Jina AI
美团技术团队
The Cloudflare Blog
M
MIT News - Artificial intelligence
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
S
Schneier on Security
C
Check Point Blog
Project Zero
Project Zero
The Hacker News
The Hacker News
Scott Helme
Scott Helme
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Cisco Talos Blog
Cisco Talos Blog
P
Privacy International News Feed
SecWiki News
SecWiki News
Latest news
Latest news
MongoDB | Blog
MongoDB | Blog
S
Secure Thoughts
Google Online Security Blog
Google Online Security Blog
F
Fortinet All Blogs
博客园 - 三生石上(FineUI控件)
H
Help Net Security
TaoSecurity Blog
TaoSecurity Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Last Week in AI
Last Week in AI
P
Privacy & Cybersecurity Law Blog
Forbes - Security
Forbes - Security
G
GRAHAM CLULEY
N
Netflix TechBlog - Medium
L
Lohrmann on Cybersecurity
A
About on SuperTechFans
T
The Exploit Database - CXSecurity.com
C
Cisco Blogs
PCI Perspectives
PCI Perspectives
大猫的无限游戏
大猫的无限游戏
T
Troy Hunt's Blog
H
Hacker News: Front Page
Vercel News
Vercel News

元视角

.NET 生态下的 Agent 框架选型:从 ReAct 到原生推理 - 元视角 从「能用」到「好用」:LLM 流式响应实现方式的探索之路 - 元视角 当我用 2000 条聊天记录,让 AI 为我画一幅自画像 - 元视角 基于 Supabase 的 AI 应用开发探索 - 元视角 微博 × MCP:社交媒体新玩法解锁 - 元视角 四点钟海棠花未眠 - 元视角 Semantic Kernel × MCP:智能体的上下文增强探索 - 元视角 基于 K-Means 聚类分析实现人脸照片的快速分类 - 元视角 容器技术驱动下的代码沙箱实践与思考 - 元视角 温故而知新:后端通用查询方案的再思考 - 元视角 浅议 CancellationToken 在前后端协同取消场景中的应用 - 元视角 Semantic Kernel 视角下的 Text2SQL 实践与思考 - 元视角 关于 ChatGPT 的流式传输,你需要知道的一切 - 元视角 RAG 的是与非、Rewrite 和 Rerank - 元视角 使用 EFCore 和 PostgreSQL 实现向量存储及检索 - 元视角 基于 LLaMA 和 LangChain 实践本地 AI 知识库 - 元视角 使用 llama.cpp 在本地部署 AI 大模型的一次尝试 - 元视角 如何为 Git 配置多个 SSH Key - 元视角 C# 使用 LibUsbDotNet 实现 USB 设备检测 - 元视角 基于 C# 实现样式与数据分离的打印方案 - 元视角 基于 SVG 的图形交互方案实践 - 元视角 前端视频播放技术概览 - 元视角 温故而知新,再话 Python 动态导入 - 元视角 后 GPT 时代,NLP 不存在了? - 元视角 视频是不能 P 的系列:使用 Milvus 实现海量人脸快速检索 - 元视角 GDI+下字体大小自适应方案初探 - 元视角 小爱音箱集成 ChatGPT 的不完全教程 - 元视角 程序员视角下的三体世界随想 - 元视角 关于 Docker 容器配置信息的渐进式思考 - 元视角 在 Docker 容器内集成 Crontab 定时任务 - 元视角 为你的服务器集成 LDAP 认证 - 元视角 似花还似非花 - 元视角 视频是不能 P 的系列:使用 Dlib 实现人脸识别 - 元视角 浅议分布式链路追踪与日志的整合 - 元视角 关于 Git 大文件上传这件小事 - 元视角 .NET 进程内队列 Channel 的入门与应用 - 元视角 使用 Fody 实现 .NET 的静态编织 - 元视角 .NET Core + ELK 搭建可视化日志分析平台(下) - 元视角 聊一聊前端图片懒加载背后的故事 - 元视角 支持外部链接跳转的 Vue Router 扩展实现 - 元视角 视频是不能 P 的系列:OpenCV 和 Dlib 实现表情包 - 元视角 不得不说的 ASP.NET Core 集成测试 - 元视角 再议 DDD 视角下的 EFCore 与 领域事件 - 元视角 Vue.js 前端项目容器化部署实践极简教程 - 元视角 再见,人间四月天 - 元视角 Python 图像风格化迁移助力画家梦想 - 元视角 利用 ASP.NET Core 中的标头传播实现分布式链路追踪 - 元视角 利用 gRPC 实现文件的上传与下载 - 元视角 七种武器:延迟队列的原理和实现总结 - 元视角 gRPC 流式传输极简入门指南 - 元视角 Envoy 集成 Jaeger 实现分布式链路追踪 - 元视角 浅议非典型 Web 应用场景下的身份认证 - 元视角 gRPC 借助 Any 类型实现接口的泛化调用 - 元视角 分布式丛林探险系列之 Redis 集群模式 - 元视角 分布式丛林探险系列之 Redis 主从复制模式 - 元视角 通过 Python 预测 2021 年双十一交易额 - 元视角 gRPC 搭配 Swagger 实现微服务文档化 - 元视角 SSL/TLS 加密传输与数字证书的前世今生 - 元视角 使用 Python 自动识别防疫健康码 - 元视角 你不可不知的容器编排进阶技巧 - 元视角 ASP.NET Core 搭载 Envoy 实现 gRPC 服务代理 - 元视角 再话 AOP,从简化缓存操作说起 - 元视角 ASP.NET Core 搭载 Envoy 实现微服务身份认证(JWT) - 元视角 ASP.NET Core 搭载 Envoy 实现微服务的监控预警 - 元视角 ASP.NET Core 搭载 Envoy 实现微服务的反向代理 - 元视角 ASP.NET Core gRPC 打通前端世界的尝试 - 元视角 EFCore 实体命名约定库:EFCore.NamingConventions - 元视角 ASP.NET Core gRPC 集成 Polly 实现优雅重试 - 元视角 ASP.NET Core gRPC 健康检查的探索与实现 - 元视角 ASP.NET Core gRPC 拦截器的使用技巧分享 - 元视角 SnowNLP 使用自定义语料进行模型训练 - 元视角 使用 HttpMessageHandler 实现 HttpClient 请求管道自定义 - 元视角 ABP vNext 的实体与服务扩展技巧分享 - 元视角 ABP vNext 对接 Ant Design Vue 实现分页查询 - 元视角 源代码探案系列之 .NET Core 跨域中间件 CORS - 元视角 源代码探案系列之 .NET Core 限流中间件 AspNetCoreRateLimit - 元视角 源代码探案系列之 .NET Core 并发限制中间件 ConcurrencyLimiter - 元视角 通过 EmbededFileProvider 实现 Blazor 的静态文件访问 - 元视角 低代码,想说爱你不容易 - 元视角 记一次失败的 ThoughtWorks 面试经历 - 元视角 从 C# 1.0 到 C# 9.0,历代 C# 语言特性一览 - 元视角 通过 Python 分析 2020 年全年微博热搜数据 - 元视角 使用多线程为你的 Python 爬虫提速的 N 种姿势,你会几种? - 元视角 实现网页长截图的常见思路总结 - 元视角 温故而知新,由 ADO.NET 与 Dapper 所联想到的 - 元视角 视频是不能 P 的系列:OpenCV 人脸检测 - 元视角 作为技术宅的我,是这样追鬼滅の刃的 - 元视角 使用 Python 抽取《半泽直树》原著小说人物关系 - 元视角 厉害了!打工人用 Python 分析西安市职位信息 - 元视角 使用 dotTrace 对 .NET 应用进行性能分析与优化 - 元视角 一道 HashSet 面试题引发的蝴蝶效应 - 元视角 基于选项模式实现.NET Core 的配置热更新 - 元视角 Dapper.Contrib 在 Oracle 环境下引发 ORA-00928 异常问题的解决 - 元视角 .NET Core 中对象池(Object Pool)的使用 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(下):EventBus 篇 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(中):RabbitMQ 篇 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(上):基础篇 - 元视角 记一次从已损坏的 Git 仓库中找回代码的经历 - 元视角 .NET Core 原生 DI 扩展之属性注入实现 - 元视角 .NET Core 原生 DI 扩展之基于名称的注入实现 - 元视角
基于 Python 和 Selenium 实现 CSDN 一键三连自动化 - 元视角
飞鸿踏雪 · 2021-01-20 · via 元视角

最近一段时间,博主感觉到了某种危机感,或者说是每一个不再年轻的人都会面对的问题,即,怎么面对来自更年轻的“后浪”们的压力,自打国内 IT 行业有了 35 岁这个不成文的“门槛”以后,年轻的“后浪”们仿佛有了更多将“前浪”们拍死在岸上的勇气,我辈忍不住要叹一声后生可畏啊!我认识的 Catcher Wong 正是这样一位大佬,此君虽然比我小三岁,可在技术的广/深度以及经验的丰富程度上,足以令我这个”老人”汗颜,单单 EasyCaching 这一项,就令人望尘莫及啦!我看着他的时候,一如当年 Wesley 大哥看着我的时候,可能这就是某种轮回,姑且执浊酒一杯,致我们终将老去的青春。

不正经的 Kimol 君

关注Kimol 君,最早源于他在我博客里留言,作为礼尚往来,我回访了他的博客,然后发现此人人如其名,非常的”不正经”,他的博客访问量出奇地高,在 CSDN 里写博客多年,深知现在不比从前有运营梦鸽和大白两位小姐姐帮忙推荐到首页,普通的内容很少有机会拥有这样的曝光机会,而像 郭霖 这种从 10 年前后开始写移动开发系列博客的“大神”或者是以图形学为主要写作方向的 诗人“浅墨” ,在通篇都是干货的情况下,长期保持着不错的人气。

这萌萌哒求赞的表情我是做不来的 这萌萌哒求赞的表情我是做不来的

起初,我以为此君的流量来自于标题党,譬如《学会这招,小姐姐看你的眼神将不一样》《震惊!小伙竟然用 Python 找出了马大师视频中的名场面》这几篇,非常像 UC 编辑部和微信公众号的风格。我是一个擅长学习的人,主动去借鉴了他博客中的优点,比如尝试使用轻松、幽默的文风,在文章开头放入目录,适当“蹭”热点等等,我甚至专门致敬了一篇博客: 《厉害了!打工人用 Python 分析西安市职位信息》。而整个 1 月份,我就只有一篇博客流量高一点,就这还不是特别正经的”技术”博客,而此君的流量则是一个又一个的 1w+ ,可我实在想不通,一个不到 100 行的 Python 脚本,真就值得花那么多的流量,真就值得上百条的评论吗?这里放张图大家感受一下:

不知道该说什么好 不知道该说什么好

仔细研究了他博客里评论的风格,发现有大量类似“夸夸群”风格的评论,就是那种读起来确实像对方读过了你的文章,可实际一想就觉得这是那种“放之四海而皆准”的话。我最近知道了一位大佬的博客,我惊奇地发现,此君居然在上面留过言,我顺着大佬的博客继续找,发现一个非常有意思的事情,此君曾经给我留言过的内容,居然出现在了别人的博客底下,而从这篇博客的评论里继续找,你会发现好像有一个团队专门在做这种事情,互相点赞、互相评论,甚至这些留言都是来自一篇博客都没有的”新人”,至此,基本可以断定,此君“不讲武德”,用作弊的方式在刷流量!当然,他自己都承认了:

作弊实锤 作弊实锤

年轻人不讲”武德”

OK,既然现在的年轻人都把心思用到这种事情上,作为一个老年人,必须要让他知道什么叫“耗子尾汁”,我们技术做一点正经事儿不行吗?其实,博客园的博客质量相比 CSDN 是要高出许多的,而正因为如此,CSDN 在全力转在线教育/课程以后,博客这个板块就再无往日的“生气”,如果每个人都像他一样,天天跑别人底下刷评论,发一点不痛不痒的话,甚至是推广某个小圈子里的 QQ 群,那真正优质的内容又如何能被大家看到呢?博主曾经加过这样的 QQ 群,你以为是交流技术的群吗?其实是为了推广某个 Python 课程,博主本想交流一下“半泽直树”,然后就被群管理员给删除了!此君大概是抓取 Python 板块排名靠前的博客,通过程序来刷存在感。

对此,我想说,这玩意儿用 Selenium + Python 简直和闹着玩一样,毕竟在了解网页结构以后,直接上 jQuery 操作 DOM 即可,甚至连抓包都不需要,不信你看:

import requests
from bs4 import BeautifulSoup
import fake_useragent
import os, json, time, random
from selenium import webdriver
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class Proxy:

    def __init__(self, profile):
        os.environ['TEMPDIR'] = os.path.join(os.path.abspath('.'), 'profile')
        firefoxProfile = webdriver.FirefoxProfile(profile) 
        fireFoxOptions = webdriver.FirefoxOptions()
        self.driver = webdriver.Firefox(
            firefox_options=fireFoxOptions, 
            firefox_profile=firefoxProfile
        )

    # 批量点赞
    def vote(self, urls):
        '''
        对指定的一组博客地址批量进行点赞
        '''
        for url in urls:
            self.driver.get(url)
            time.sleep(3)
            flag = self.driver.execute_script("return $('#is-like-span').text().trim()") == "已赞"
            if not flag:
                self.driver.execute_script("$('#is-like-span').click()")
            time.sleep(1)
    
    # 批量收藏
    def collect(self, urls):
        '''
        对指定的一组博客地址批量进行收藏
        '''
        for url in urls:
            self.driver.get(url)
            time.sleep(3)
            flag = self.driver.execute_script("return $('#is-collection').text()") == "已收藏"
            if not flag:
                self.driver.execute_script("$('#is-collection').click()")
                self.driver.execute_script("$('.csdn-collection-submit').click()")
            time.sleep(1)
    
    # 批量关注
    def follow(self, urls):
        '''
        对指定的一组博客地址批量进行关注
        '''
        for url in urls:
            self.driver.get(url)
            time.sleep(3)
            flag = '已关注' in self.driver.execute_script(
                "return $($('.toolbox-list').children()[6]).find('a').text().trim()"
            )
            if not flag:
                self.driver.execute_script("$($('.toolbox-list').children()[6]).find('a').click()")
            time.sleep(1)
    
    # 批量一键三连
    def iloveyuou(self, urls):
        '''
        对指定的一组博客地址批量进行三连
        '''
        for url in urls:
            self.driver.get(url)
            time.sleep(3)
            self.driver.execute_script("$($('.toolbox-list').children()[7]).find('p').click()")
            time.sleep(1)
    
    # 批量留言
    def comment(self, urls, texts):
        '''
        对指定的一组博客地址批量进行评论
        '''
        for url in urls:
            self.driver.get(url)
            time.sleep(3)
            text = random.choice(texts)
            self.driver.execute_script(f"$('#comment_content').text('{text}')")
            self.driver.execute_script(f"$('.btn-comment').click()")
            # CSDN对评论间隔有要求,那就再睡一会儿
            time.sleep(5)
    
    # 热门文章
    def hotRank(self, channel):
        '''
        抓取某个话题下的热门文章
        '''
        url = f'https://blog.csdn.net/phoenix/web/blog/hotRank?page=0&pageSize=25&child_channel={channel}'
        headers = {
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0',
            'Cookie':'uuid_tt_dd=10_220300310-1611402514139-727015; dc_session_id=10_1611402514139.129755; dc_sid=37a633fe075b2698beeae6fb9c306fb4'
        }
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        data = json.loads(response.text)
        if (data['code'] == 200 and data['message'] == 'success'):
            return list(map(lambda x:x['articleDetailUrl'], data['data']))
        else:
            return []

我们都知道,在通常情况下,Selenium 每次运行时都会打开一个浏览器, 可这个浏览器呢,相对于我们平时使用的浏览器来说是“独立”的,因为细心的朋友一定会发现,虽然我们在 Chrome 或者 Firefox 中早已登录过了某个网站,可此时此刻,当 Selenium 启动浏览器窗口的时候,我们发现这个网站依然是需要登录的。为什么要讨论这个问题呢?因为如果我们希望对 CSDN 实现“一键三连”,登录这一步是必不可少的步骤。那么,有没有一种办法,可以让 Selenium 共享我们本地浏览器中的 Cookie 信息呢?因为只要有了 Cookie,我们就可以专注于实现“一键三连”这部分。相信大家都看过上面的代码啦,答案当然是有的,我们为其指定一个配置文件的路径即可:

# 设置 Firefox 配置文件
# 默认路径:C:\\Users\\<User>\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\XXXX.default
# 参考链接:https://support.mozilla.org/zh-CN/kb/用户配置文件
profile_dir = 'C:\\Users\\YuanPei\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\xypbnthd.default-release'
firefoxProfile = webdriver.FirefoxProfile(profile_dir) 
fireFoxOptions = webdriver.FirefoxOptions()
webdriver.Firefox(firefox_options=fireFoxOptions, firefox_profile=firefoxProfile)

# 设置 Chrome 配置文件
# 默认路径:C:\\Users\\<User>\\AppData\Local\Google\Chrome\User Data
profile_dir = 'C:\\Users\\YuanPei\\AppData\Local\Google\Chrome\User Data'
chromeOptions = webdriver.ChromeOptions()  
chromeOptions.add_argument('user-data-dir=' + os.path.abspath(profile_dir))  
webdriver.Chrome(chrome_options=chromeOptions)

这样,Selenium 启动的就不再是一个“裸”的浏览器,我们平时使用的各种配置、插件等等都会被原封不动地加载到 Selenium 中,这其中同样了我们的 Cookie,所以,当大家看到我的代码的时候,会发现这里没有做任何登录相关的事情,这其实是在用“时间”换取技术实现的“简单”,因为要额外加载大量的信息,所以,Selenium 启动的时候会变得缓慢起来,经过博主自己测试,Firefox 启动大概需要 1 分钟左右,熬过这 1 分钟接下来就是坦途啦!

其实,除此以外,关于登录这个问题,我们还有一种方案是对 Cookie 进行持久化。简而言之,就是利用 Selenium 的get_cookies()add_cookie() 这一组 API,第一次打开某个网站的时候,首先人为地或者模拟登录,此时可以获得 Cookie 并对其进行序列化,而访问那些需要登陆的资源时,则可以对 Cookie 进行反序列化并将其加载到 Selenium 环境中,基本的代码示例如下:

# 保存Cokie到本地文件
cookies = driver.get_cookies()
with open("cookies.txt", "w") as fp:
	json.dump(cookies, fp)

# 从本地文件加载Cookie
with open("cookies.txt", "r") as fp:
	cookies = json.load(fp)
	for cookie in cookies:
		driver.add_cookie(cookie)

下面来做一个简单的演示, CSDN 有一个类似微博热搜的 博客榜单。这里,我们会从中筛选前 5 的博客链接来进行“一键三连”操作。与此同时,博主选取了一部分这些年轻人们喜欢用的评论,就在刚刚,我在这篇博客 《第十二届蓝桥杯模拟赛 Python 组(第一期)》 下面再次发现 Kimol 君 的身影,年轻人你不讲武德啊!我就想起了《开讲啦》里面惹恼易中天教授的那位学生,一个人的文章写得好,大家愿意去读去看,这自然是好事,可正因为梦鸽和大白这些小姐姐们都不在了,这个社区的内容质量完全由点赞、评论、收藏数这些因素在左右着,作为一名博客作者,我更希望别人能真的在读完我的文章后,或者能找出我考虑不周的地方,或者可以就某一个问题深入讨论一番,我发现社区里都喜欢动辄加别人 QQ 或者微信,可如果这种毫无意义地灌水的评论,这一切又有什么意义呢?

# 如果你经常收到这些评论,千万不要“飘”
# 你觉得这些话都是真心的吗?
comments = [
    '代码之路任重道远,愿跟博主努力习之。',
    '学起来,头秃的那种~',
    '写的太好了,很实用',
    '好文!希望博主以后多多分享哈!',
    '哇,好棒啊,崇拜的小眼神,欢迎回赞,回评哦~~~',
    '收藏从未停止,学习从未开始。',
    '大佬,看了您的文章,内心的仰慕之情油然而生,赶紧给大佬点个赞!',
    '太赞了!666666'
]
proxy = Proxy('C:\\Users\\YuanPei\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\xypbnthd.default-release')
# 热搜前5名的文章
urls = proxy.hotRank('python')[:5]
# 批量留言,刷存在感
proxy.comment(urls, comments)
# 一键三连
proxy.iloveyuou(urls)

当然啦,像我这里提供的关于点赞(vote)、收藏(collect)、关注(follow)等等方法,同样是可以使用的,这里就不再一一例举啦!本身都是基于 jQuery 来操作 DOM,理解上应该没有太大难度,虽然我不大喜欢用 jQuery 写业务代码,可对于爬虫这种事情,自然是越简单越好,因为我不想再去学一门操作 DOM 的语言:XPath, 而关于 Selenium 驱动的安装、配置等细节,可以参考博主的这篇文章:

作为技术宅的我,是这样追鬼滅の刃的

博主最近新开了一个付费专栏:Python 数据挖掘系列,主要介绍关于爬虫、PyECharts、结巴分词、Pandas、Matplotlib、SnowNLP、OpenCV 等数据挖掘相关内容,如果大家喜欢或者感兴趣,欢迎订阅。好了,以上就是这篇博客的全部内容啦,欢迎大家在评论区,就你对于这篇博客的想法或者意见进行讨论,再次谢谢大家!如果 Kimol 君 恰好读至此处,最好能一键三连,我权当作为你打广告的广告费啦,哈哈!