前言
近来好几个月都没有更新过简书的文章了,一来是年底之前工作上非常忙,二来是南方的湿冷天气直接把人给冻懒了。之前打心底里立的坚持写作的Flag早已烟消云散了,我那有进取心的一部分身体感到很是蓝瘦(难受),于是乎决定重新拾起这份写作的热情,今天来给大家分享一个通过Python编写的自动化脚本刷取博客访问量的方法。
事情概要
由于年前有个朋友需要刷取某浪博客的阅读量,需要刷到20W+,于是乎找上我,希望我能帮他搞定。于是我在网上看了一些大牛们的解题思路和代码示例,抛开编程语言,总结起来都是爬虫思路,只是实现方式上有些优劣的差异。
基本上都是针对只要打开网页,内容读取完成就算一个阅读量或者访问量这一类的博主网站,拿Python来讲可以通过:Request/urlib+代理池+多线程Thread来实现。
如何寻找代理池可自行百度谷歌或者访问这个网站代理
思路就是可以通过Request模块爬取网页内容,再用BeautifulSoup模块解析详细的网页内容,获取到代理地址同时测试每个代理地址是否可用,把可用的地址记录下来得到一个代理池,再使用代理池中的地址去刷取目标博客的URL网页。
使用代理池的目的是为了绕开大部分的博客系统都有封IP的防爬策略,单个IP访问的次数或者频率过高会被封杀。
还有另外一点需要注意的就是使用Request/urlib模块访问博客的时候需要设定好Http headers中的内容,模拟浏览器发起请求,可随机使用多种浏览器的的User-agent标识,防止被博客系统的防爬虫策略给干掉。
但是今天我主要写一下另外一种情况,因为我发现这个某浪的博客系统对于用于打开网页,内容读取完成是不算阅读量的,它有一定的业务逻辑,需要浏览器打开网页,网页内容中有JS控制触发了业务请求,才算阅读量,这就要求我采用另外一种思路来解决这个问题,于是乎就有了下面的内容。
方法
这里我使用的是简单直接的笨方法:通过编写python代码实现自动打开浏览器访问指定URL,同时多线程控制实现每个URL在浏览器中定时刷新。
我们需要用到python的webbrower模块,此模块主要常用的几个方法如下:
# 在系统的默认浏览器中访问url地址,如果new=0,url会在同一个浏览器窗口中打开;
# 如果new=1,新的浏览器窗口会被打开;
# new=2新的浏览器tab会被打开。
# new参数的解释不一定适用所有浏览器,具体浏览器有具体差异比如chrome总是新开一个tab
webbrowser.open(url, new=0, autoraise=True)
# 其实调用的还是上面的open
webbrowser.open_new(url)
# 同上
webbrowser.open_new_tab(url)
# 方法可以获取到系统浏览器的操作对象。
webbrowser.get()
# 方法可以注册浏览器类型
webbrowser.register()
最后一个register方法的使用和模块支持的允许被注册的浏览器类型可以参阅如下一篇博客:
http://www.cnblogs.com/hongten/p/hongten_python_webbrowser.html
编码
首先编写一个通过webbrower模块可以自动打开一个URL地址并自动刷新的函数供多线程来调用。考虑到最大限度的利用计算机性能,方法支持多线程同时打开系统默认浏览器和谷歌浏览器来刷新URL(如果系统默认浏览器就是Chrome的同学可以把代码简单改下,微笑)
"""
此方法用于打开博客网站URL,目前此方法是在我本机Mac下跑的,如果是Windows或者Linux的朋友
需要稍作修改,只要修改注册chrome的那一行代码,chrome运行文件路径即可,windows下是chrome.exe的全路径
@:param url 待刷取博客URL地址
@:param interval_time 自动刷新访问的间隔时间(视个人设备和网络实际情况设定)
@:param open_defalut 默认为True用操作系统设定的默认浏览器打开,False为使用chrome
"""
def open_brower_auto_refresh(url, interval_time, open_default=True):
global count
temp = 1
while True:
if open_default:
brower = web.open(url, new=0, autoraise=False)
else:
chrome = web.get("chrome")
chrome.open(url)
temp = temp + 1
#防止chrome浏览器tab页开启太多,内存耗尽
if temp > 20:
temp = 1
os.system('pkill -9 Chrome')
web.register("chrome", None, web.BackgroundBrowser(r'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'))
time.sleep(interval_time)
count = count+1
整个模块包含多线程的完整代码如下:
# coding=utf-8
"""
此模块用于控制用户自动打开浏览器,浏览博客网站URL,刷取阅读量
若遇到会封单个IP的博客网站,可以考虑再拓展动态设置网络代理
每个URL会对应一个独立的访问线程
"""
import webbrowser as web
import time
import threading
import os
# 用于全局统计刷取了访问量总数
count = 0
"""
此方法用于打开博客网站URL,目前此方法是在我本机Mac下跑的,如果是Windows或者Linux的朋友
需要稍作修改,只要修改注册chrome的那一行代码,chrome运行文件路径即可
@:param url 待刷取博客URL地址
@:param interval_time 自动刷新访问的间隔时间(视个人设备和网络实际情况设定)
@:param open_defalut 默认为True用操作系统设定的默认浏览器打开,False为使用chrome
"""
def open_brower_auto_refresh(url, interval_time, open_default=True):
global count
temp = 1
while True:
if open_default:
brower = web.open(url, new=0, autoraise=False)
else:
chrome = web.get("chrome")
chrome.open(url)
temp = temp + 1
if temp > 20:
temp = 1
os.system('pkill -9 Chrome')
web.register("chrome", None, web.BackgroundBrowser(r'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'))
time.sleep(interval_time)
count = count+1
if __name__ == '__main__':
# 多线程启动浏览器,每个页面一个线程,自动延时的刷新间隔时间
interval_time = 2
#需要刷新的博客列表URL定义在这里
url_list = ["https://www.jianshu.com/u/93e6c3dd7c46",
"https://www.jianshu.com/p/1e48e68c6678"]
for url in url_list:
t2 = threading.Thread(target=open_brower_auto_refresh,
args=(url, interval_time+1))
t2.start()
time.sleep(1)
for url in url_list:
t4 = threading.Thread(target=open_brower_auto_refresh,
args=(url, interval_time, False))
t4.start()
while True:
print "当前已刷新阅读量总数:"+str(count)
time.sleep(60)
模块运行效果图:
auto_ref.gif
代码是在Mac笔记本python 2.7.15版本上运行,亲测Chrome浏览器的性能要好些,因为每次访问url Chrome都会新开一个tab再加上本身浏览器的性能优秀,所以使用chrome浏览器时interval_time可以相对设置小一点,相比其他浏览器。
后记优化思路
- 如果遇到比较变态的反爬虫博客系统限制了单个IP的浏览访问频率和次数,可以考虑结合代理池来绕过,使用webbrower模块访问URL之前先设置好浏览器网络代理再发起请求。
- 基于绿色环保节能和收益最大化的思路,使用一台电脑一直持续的做这个事情,说实话比较浪费,能耗较高。可以把上面的程序代码放到一台树莓派上面跑,毕竟树莓派使用的是手机充电头5V 2A的电源供电,相比一台电脑或者笔记本来说这是指数级的能耗比吧。
最后,如果有同学还有其它好的解题思路,可以在留言区评论一下,大家互相学习,好的话我会帮你置顶评论,谢谢。
当然了,提升博客的访问量还是需要通过提高博客内容质量,创作出优秀新颖的内容来吸引大众,靠刷取阅读量的博主一看就会露馅的,这条路终究是无法走长久。
网友评论