大数据 爬虫Python AI SqlPython学习资料整理

来!用python爬一爬“不知知网翟博士”的微博超话

2019-04-08  本文已影响1人  老白和他的爬虫

据说“不知知网翟博士”以一己之力提升了中国研究生的毕业标准,那今天就用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

这五步大概就是我们整体的思路,但是看上去简单,实现可没有那么容易,在这个过程中会遇到很多的问题,比如我举个例子:

  1. 我们需要不停的“刷”,就像我们自己平时用手机刷微博一样,只有我们不停的刷新,他才会有数据出来,所以我们必须模拟滑动
  2. 渣浪随时可能拒绝我们的访问,我们必须适当调低速度来更加的拟人化,使得不被发现是机器人
  3. 网络出现问题的话,我们爬虫无法继续解析界面,所以我们要边滑动页面边存储当前已解析出来的数据
  4. 我们很可能面临,爬虫中断的问题,重新爬取数据必须保证已爬取的数据不被重复存储,所以必须去重

以及等等很多的问题,我就不一一列举了,总之在我编写代码的过程中,我觉得需要解决的问题基本都解决了,如果你有问题欢迎在后台留言

3.代码编写

这里需要有两个文件,一个用来爬取数据,一个用来存储数据,在运行下面代码前,你要保证几点:

  1. 车速要快,网速要稳
  2. 正在滚动解析页面时尽量不要再用电脑做其他的事
  3. 出现这个弹框,尽快手动取消,不过他一般只会在爬虫开始时出现两次
image.png

今日份代码公众号回复: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)

最后,关注一波吧

image.png
上一篇 下一篇

猜你喜欢

热点阅读