来!用python爬一爬“不知知网翟博士”的微博超话
据说“不知知网翟博士”以一己之力提升了中国研究生的毕业标准,那今天就用python来采集一下微博上关于翟博士的超话内容都有什么
欢迎关注公众号:老白和他的爬虫
寒假在家的时候看到了翟博士的微博,我酸了
image.png
怎么人家四年,戏也拍了,人也火了,论文倒不用写,博士还毕业了,北大也特么进了,头发还那么多,让我这个十八流程序员怎么能不酸
image.png
不过后来我就知道人家头发那么多的原因了
image.png
转发这个翟博士,你也能不用写论文就毕业(看看人家这duangduang的发量)
image.png
废话不多说了,来爬数据吧
翟博士微博超话爬虫
- 明确需求
- 模拟浏览器
- 爬取数据
1.明确需求
应某位产品经理的需求,这次的爬虫需要爬取大当量的微博数据,大概在十万到百万级别,但是渣浪有一个很不好的一点,就是你连续访问太多次,就会对你进行封锁,而且网页版的微博,只有50页的微博结果,顶多1000来条数据。所以我就转而对手机端微博进行数据爬取,因为我们在手机端刷微博的话,只要你一直往下刷,他就可以一直有数据,这就解决了网页版的数据限制,但是手机端同样面临不能访问太频繁的问题,如果短时间内访问太多,服务器会判断你是机器,会封锁你的ip一段时间,导致我们的爬虫中断。
我们今天想做的,是爬取给定关键词的超话,然后爬取每一个超话下面的关于“实时”和“热门”下的每一条微博内容,你可以看到这样数据量很大吧 这里的关键词完全由你定,只不过翟博士太火了,我们蹭下热度哈哈
2.模拟浏览器
上一篇文章 微博任意关键词爬虫——使用selenium模拟浏览器 初步讲了一下selenium,我个人觉得selenium对新手爬虫学习者是一个非常值得学习的包,掌握了selenium,我可以保证 只要你能在浏览器上看到的东西,你都能采集下来 如果你有学习这个包的需求的话,你可以在后台留言,我会根据需求再来出学习的推文。
我们来在浏览器上模拟一遍我们的爬虫,爬虫的思路也和我们这个过程相符合
第一步,登录
image.png
第二步,搜索框输入“翟博士”,并点击搜索
image.png
第三步,依次选择话题
image.png
第四步,进入话题页面
image.png
第五步,点击“实时”或者“热门”,并copy当前页面的微博
image.png
这五步大概就是我们整体的思路,但是看上去简单,实现可没有那么容易,在这个过程中会遇到很多的问题,比如我举个例子:
- 我们需要不停的“刷”,就像我们自己平时用手机刷微博一样,只有我们不停的刷新,他才会有数据出来,所以我们必须模拟滑动
- 渣浪随时可能拒绝我们的访问,我们必须适当调低速度来更加的拟人化,使得不被发现是机器人
- 网络出现问题的话,我们爬虫无法继续解析界面,所以我们要边滑动页面边存储当前已解析出来的数据
- 我们很可能面临,爬虫中断的问题,重新爬取数据必须保证已爬取的数据不被重复存储,所以必须去重
以及等等很多的问题,我就不一一列举了,总之在我编写代码的过程中,我觉得需要解决的问题基本都解决了,如果你有问题欢迎在后台留言
3.代码编写
这里需要有两个文件,一个用来爬取数据,一个用来存储数据,在运行下面代码前,你要保证几点:
- 车速要快,网速要稳
- 正在滚动解析页面时尽量不要再用电脑做其他的事
- 出现这个弹框,尽快手动取消,不过他一般只会在爬虫开始时出现两次
今日份代码公众号回复:20190408,可自动获得代码和驱动
第一个文件是是存储数据的,文件名为excelSave.py
import xlrd
import xlwt
from xlutils.copy import copy
def write_excel_xls(path, sheet_name, value):
index = len(value) # 获取需要写入数据的行数
workbook = xlwt.Workbook() # 新建一个工作簿
sheet = workbook.add_sheet(sheet_name) # 在工作簿中新建一个表格
for i in range(0, index):
for j in range(0, len(value[i])):
sheet.write(i, j, value[i][j]) # 像表格中写入数据(对应的行和列)
workbook.save(path) # 保存工作簿
print("写入数据成功!")
def read_excel_xls(path):
data = []
workbook = xlrd.open_workbook(path) # 打开工作簿
sheets = workbook.sheet_names() # 获取工作簿中的所有表格
worksheet = workbook.sheet_by_name(sheets[0]) # 获取工作簿中所有表格中的的第一个表格
if worksheet.nrows == 1:
print("目前是第一行")
else:
for i in range(1, worksheet.nrows): #从第二行取值
dataTemp = []
for j in range(0, worksheet.ncols):
#print(worksheet.cell_value(i, j), "\t", end="") # 逐行逐列读取数据
dataTemp.append(worksheet.cell_value(i, j))
data.append(dataTemp)
return data
def write_excel_xls_append_norepeat(path, value):
workbook = xlrd.open_workbook(path) # 打开工作簿
sheets = workbook.sheet_names() # 获取工作簿中的所有表格
worksheet = workbook.sheet_by_name(sheets[0]) # 获取工作簿中所有表格中的的第一个表格
rows_old = worksheet.nrows # 获取表格中已存在的数据的行数
new_workbook = copy(workbook) # 将xlrd对象拷贝转化为xlwt对象
new_worksheet = new_workbook.get_sheet(0) # 获取转化后工作簿中的第一个表格
data_temp = []#保存未重复的数据
for i in range(0, len(value)):
data = read_excel_xls(path)
if value[i] not in data:
data_temp.append(value[i])
else:
print("数据重复,不插入excel表")
for i in range(0, len(data_temp)):
for j in range(0, len(data_temp[i])):
new_worksheet.write(i+rows_old, j, data_temp[i][j]) # 追加写入数据,注意是从i+rows_old行开始写入
new_workbook.save(path) # 保存工作簿
print("【追加】写入数据成功!")
第二个是爬虫主程序,文件名为weibo.py
import time
import xlrd
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import os
import excelSave as save
# 用来控制页面滚动
def Transfer_Clicks(browser):
try:
browser.execute_script("window.scrollBy(0,document.body.scrollHeight)", "")
except:
pass
return "Transfer successfully \n"
#判断页面是否加载出来
def isPresent():
temp =1
try:
driver.find_elements_by_css_selector('div.line-around.layout-box.mod-pagination > a:nth-child(2) > div > select > option')
except:
temp =0
return temp
#把超话页面滚动到底
def SuperwordRollToTheEnd():
before = 0
after = 0
n = 0
timeToSleep = 500
while True:
before = after
Transfer_Clicks(driver)
time.sleep(3)
elems = driver.find_elements_by_css_selector('div.m-box')
print("当前包含超话最大数量:%d,n当前的值为:%d,当n为15无法解析出新的超话" % (len(elems),n))
after = len(elems)
if after > before:
n = 0
if after == before:
n = n + 1
if n == 15:
print("当前包含最大超话数为:%d" % after)
break
if after > timeToSleep:
print("抓取到%d多条超话,休眠1分钟" % timeToSleep)
timeToSleep = timeToSleep + 500
time.sleep(60)
#插入数据
def insert_data(elems,path,name,yuedu,taolun):
for elem in elems:
workbook = xlrd.open_workbook(path) # 打开工作簿
sheets = workbook.sheet_names() # 获取工作簿中的所有表格
worksheet = workbook.sheet_by_name(sheets[0]) # 获取工作簿中所有表格中的的第一个表格
rows_old = worksheet.nrows # 获取表格中已存在的数据的行数
rid = rows_old
#用户名
weibo_username = elem.find_elements_by_css_selector('h3.m-text-cut')[0].text
weibo_userlevel = "普通用户"
#微博等级
try:
weibo_userlevel_color_class = elem.find_elements_by_css_selector("i.m-icon")[0].get_attribute("class").replace("m-icon ","")
if weibo_userlevel_color_class == "m-icon-yellowv":
weibo_userlevel = "黄v"
if weibo_userlevel_color_class == "m-icon-bluev":
weibo_userlevel = "蓝v"
if weibo_userlevel_color_class == "m-icon-goldv-static":
weibo_userlevel = "金v"
if weibo_userlevel_color_class == "m-icon-club":
weibo_userlevel = "微博达人"
except:
weibo_userlevel = "普通用户"
#微博内容
#分为有全文和无全文
weibo_content = elem.find_elements_by_css_selector('div.weibo-text')[0].text
shares = elem.find_elements_by_css_selector('i.m-font.m-font-forward + h4')[0].text
comments = elem.find_elements_by_css_selector('i.m-font.m-font-comment + h4')[0].text
likes = elem.find_elements_by_css_selector('i.m-icon.m-icon-like + h4')[0].text
#发布时间
weibo_time = elem.find_elements_by_css_selector('span.time')[0].text
print("用户名:"+ weibo_username + "|"
"微博等级:"+ weibo_userlevel + "|"
"微博内容:"+ weibo_content + "|"
"转发:"+ shares + "|"
"评论数:"+ comments + "|"
"点赞数:"+ likes + "|"
"发布时间:"+ weibo_time + "|"
"话题名称" + name + "|"
"话题讨论数" + yuedu + "|"
"话题阅读数" + taolun)
value1 = [[rid, weibo_username, weibo_userlevel,weibo_content, shares,comments,likes,weibo_time,keyword,name,yuedu,taolun],]
print("当前插入第%d条数据" % rid)
save.write_excel_xls_append_norepeat(book_name_xls, value1)
#获取当前页面的数据
def get_current_weibo_data(elems,book_name_xls,name,yuedu,taolun):
#开始爬取数据
before = 0
after = 0
n = 0
timeToSleep = 500
while True:
before = after
Transfer_Clicks(driver)
time.sleep(3)
elems = driver.find_elements_by_css_selector('div.card.m-panel.card9')
print("当前包含微博最大数量:%d,n当前的值为:%d, n值到30说明已无法解析出新的微博" % (len(elems),n))
after = len(elems)
if after > before:
n = 0
if after == before:
n = n + 1
if n == 30:
print("当前关键词最大微博数为:%d" % after)
insert_data(elems,book_name_xls,name,yuedu,taolun)
break
if len(elems)>maxWeibo:
insert_data(elems,book_name_xls,name,yuedu,taolun)
break
if after > timeToSleep:
print("抓取到%d多条,插入当前新抓取数据并休眠30秒" % timeToSleep)
timeToSleep = timeToSleep + 500
insert_data(elems,book_name_xls,name,yuedu,taolun)
#time.sleep(30)
#点击超话按钮,获取超话页面
def get_superWords():
time.sleep(5)
elem = driver.find_element_by_xpath("//*[@class='scroll-box nav_item']/ul/li/span[text()='话题']")
elem.click()
#获取所有超话
SuperwordRollToTheEnd()
elemsOfSuper = driver.find_elements_by_css_selector('div.card.m-panel.card26')
return elemsOfSuper
#爬虫运行
def spider(username,password,driver,book_name_xls,sheet_name_xls,keyword,maxWeibo):
#创建文件
if os.path.exists(book_name_xls):
print("文件已存在")
else:
print("文件不存在,重新创建")
value_title = [["rid", "用户名称", "微博等级", "微博内容", "微博转发量","微博评论量","微博点赞","发布时间","搜索关键词","话题名称","话题讨论数","话题阅读数"],]
save.write_excel_xls(book_name_xls, sheet_name_xls, value_title)
#加载驱动,使用浏览器打开指定网址
driver.set_window_size(452, 790)
driver.get("https://passport.weibo.cn/signin/login?entry=mweibo&res=wel&wm=3349&r=https%3A%2F%2Fm.weibo.cn%2F")
time.sleep(3)
#登陆
elem = driver.find_element_by_xpath("//*[@id='loginName']");
elem.send_keys(username)
elem = driver.find_element_by_xpath("//*[@id='loginPassword']");
elem.send_keys(password)
elem = driver.find_element_by_xpath("//*[@id='loginAction']");
elem.send_keys(Keys.ENTER)
#判断页面是否加载出
while 1: # 循环条件为1必定成立
result = isPresent()
print ('判断页面1成功 0失败 结果是=%d' % result )
if result == 1:
elems = driver.find_elements_by_css_selector('div.line-around.layout-box.mod-pagination > a:nth-child(2) > div > select > option')
#return elems #如果封装函数,返回页面
break
else:
print ('页面还没加载出来呢')
time.sleep(20)
time.sleep(5)
#搜索关键词
elem = driver.find_element_by_xpath("//*[@class='m-text-cut']").click();
time.sleep(5)
elem = driver.find_element_by_xpath("//*[@type='search']");
elem.send_keys(keyword)
elem.send_keys(Keys.ENTER)
elemsOfSuper = get_superWords()
for i in range(0,len(elemsOfSuper)):
if i >= 1:
elemsOfSuper = get_superWords()
print("当前爬取第%d个超话,共有%d个超话"% (i+1,len(elemsOfSuper)))
time.sleep(5)
element = driver.find_elements_by_css_selector('div.card.m-panel.card26')[i]
#获取话题名称,话题讨论书,阅读数
driver.execute_script('arguments[0].click()',element)
time.sleep(5)
name = driver.find_element_by_xpath("//*[@class='m-box-col m-box-dir npg-desc']/h4[@class='m-text-cut firsth']").text.replace("热搜","").replace("\n","")
yuedu_taolun = driver.find_element_by_xpath("//*[@class='m-box-col m-box-dir npg-desc']/h4[@class='m-text-cut']").text
yuedu = yuedu_taolun.split(" ")[0]
taolun = yuedu_taolun.split(" ")[1]
time.sleep(3)
shishi_element = driver.find_element_by_xpath("//*[@class='scroll-box nav_item']/ul/li/span[text()='实时']")
driver.execute_script('arguments[0].click()',shishi_element)
get_current_weibo_data(elems,book_name_xls,name,yuedu,taolun)
time.sleep(5)
remen_element = driver.find_element_by_xpath("//*[@class='scroll-box nav_item']/ul/li/span[text()='热门']")
driver.execute_script('arguments[0].click()',remen_element)
get_current_weibo_data(elems,book_name_xls,name,yuedu,taolun)
driver.back()
if __name__ == '__main__':
username = "" #你的微博登录名
password = "" #你的密码
driver = webdriver.Chrome('/Users/Desktop/python/weibo_keyword/chromedriver')#你的chromedriver的地址
book_name_xls = "/Users/Desktop/weibo.xls" #填写你想存放excel的路径,没有文件会自动创建
sheet_name_xls = '微博数据' #sheet表名
maxWeibo = 100000 #设置最多多少条微博,如果未达到最大微博数量可以爬取当前已解析的微博数量
keywords = ["翟天临",] #输入你想要的关键字,可以是多个关键词的列表的形式
for keyword in keywords:
spider(username,password,driver,book_name_xls,sheet_name_xls,keyword,maxWeibo)
最后,关注一波吧