python爬虫-模拟登陆新浪微+博爬取感兴趣人的所有信息

新浪微博的登录非常麻烦,涉及到预登录,用户名密码加密等等一系列问题

而现在pc端的新浪微博大量使用了ajax技术,必须要鼠标下滑多次才能加载一个页面的所有信息

图省事,使用了selenium_PlantomJS来模拟登陆和获取html页面,优点是实现起来很简单,缺点是速度太慢

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.common.by import By
import bs4

import time

def login(url,username,password):
    '''
    用于登录微博
    :param url:微博的登录接口 
    :param username: 用户名
    :param password: 密码
    :return: cookie
    '''
    #browser = webdriver.Chrome()                                                     #用谷歌浏览器实验
    browser = webdriver.PhantomJS("E:/phantomjs-2.1.1-windows/bin/phantomjs.exe")      #用PhantomJS
    browser.maximize_window()                      #设置窗体为最大,如果没有这一行,表单可能无法操作
    browser.get(url)                               #打开登陆用的网页

    print("开始登陆")
    username_ele = browser.find_element_by_id("loginname")    #找到用于输入用户名的表格
    username_ele.clear()                                      #清空表格
    username_ele.send_keys(username)                          #输入账户
    password_ele = browser.find_element_by_name("password")   #找到用于输入密码的表格
    password_ele.clear()                                      #清空表格
    password_ele.send_keys(password)                          #输入密码
    submit = browser.find_element_by_xpath('//*[@id="pl_login_form"]/div/div[3]/div[6]/a/span')   #找到用于提交表单的类型为submit的input
    submit.click()          #点击
    time.sleep(5)
    WebDriverWait(browser, 10).until(expected_conditions.presence_of_element_located((By.CLASS_NAME, 'WB_miniblog')))  #等待登陆页面加载完成
    if is_ele_exist(browser,"loginname"):
        print("登录失败")
        browser.quit()
        return None
    print("登陆成功")
    #return print(browser.get_cookies()
    return browser     #返回获得的cookie

def is_ele_exist(browser,id):
    '''
    根据一个id判断当前页面元素是否存在,find方法没有找到元素会抛出异常,利用异常判断元素是否存在
    :param browser: 浏览器
    :param id: 元素id
    :return: 存在返回True,不存在返回False
    '''
    try:
        s = browser.find_element_by_class_name(id)
        return True
    except:
        return False

def getweibohtml(browser,url):
    '''
    用于加载我们要爬取的用户的动态页面(单个页面上的所有信息)
    :param url: 要爬取用户的url
    :param cookie: 用于认证用户
    :return: 返回一个html页面
    '''''
    #browser = webdriver.PhantomJS("E:/phantomjs-2.1.1-windows/bin/phantomjs.exe")
    #browser = webdriver.Chrome()
    #browser.add_cookie(cookie)
    #判断broser是否可用
    if browser == None:
        return
    browser.get(url)
    browser.save_screenshot("f:\\test1.png")
    js = "var q=document.body.scrollTop=100000"       #用于下滑页面的js命令

    num = 0
    #判断翻页按钮是否出现,如果没有出现,将鼠标下滑
    while not is_ele_exist(browser,"W_pages"):
        num+=1
        browser.execute_script(js)
        print("还未找到元素")
        #最多翻页十次,防止进入死循环
        if(num>10):
            break

    print("用户的一页信息已加载完毕")
    html = browser.page_source
    return html

'''
def has_source(browser,url):
    
    判断一个微博页面是否有微博,如果没有,返回Fasle,
    最开始考虑不周到,这个函数导致需要再次用webdriver打开页面
    严重拖慢爬取速度,弃用
    
    browser.get(url)
    if is_ele_exist(browser,"WB_feed_handle"):
        return True
    else:
        return False
'''

def has_source(html):
    '''
    判断一个微博页面是否有微博,如果没有,返回Fasle,
    改良版,不用再次加载页面
    '''
    bs = bs4.BeautifulSoup(html,"lxml")
    if bs.find("div",class_="WB_detail") !=None:
        return True
    else:
        return False

def getusermessage(html):
    '''
    获取用户信息,包括头像,姓名。粉丝
    :param html: 
    :return: 
    '''
    user = {}
    bs = bs4.BeautifulSoup(html,"lxml")
    user["姓名"] = bs.find_all("h1",class_="username")[0].text
    user["头像"] = bs.find_all("p",class_="photo_wrap")[0].find_all("img")[0]["src"]
    user["认证"] = bs.find_all("div",class_="pf_intro")[0]["title"]
    messagebox = bs.find_all("div",class_="WB_innerwrap")
    messages = messagebox[0].find_all("td",class_="S_line1")
    for message in messages:
        title = message.find_all("span",class_="S_txt2")[0].text
        content = message.find_all("strong",class_="W_f16")[0].text
        user[title] = content
    print(user)
    return user
def getweibo(filename,html):
    '''
    获取一个页面上的所有信息,包括每一条微博的内容,转发,评论,点赞数量
    '''
    file = open(filename,"a",encoding="utf-8")
    beautifulsoup = bs4.BeautifulSoup(html,"lxml")
    weibos = beautifulsoup.find_all("div",class_="WB_cardwrap WB_feed_type S_bg2 ")  #获得用于显示微博的父节点
    weibonum = 0     #计算该页微博数量
    for weibo in weibos:
        #对每一个微博父节点进行处理
        weibotext = weibo.find_all("div",class_ = "WB_text W_f14") #获取微博文本内容
        message = weibotext[0].text.replace(" ","")                #取出文本中的所有空格
        weibonum+=1                                                #微博数量+1
        file.write("\n第"+str(weibonum)+"条微博内容是:"+message+"\n")

        weibopics = weibo.find_all("div",class_="WB_media_wrap clearfix")   #获取用于显示图片的标签
        if len(weibopics) != 0:                                             #判断标签是否存在
            pics = weibopics[0].find_all("img")                             #获取该标签中的所有图片
            for pic in pics:
                file.write(pic["src"]+"\n")

        weibomessages = weibo.find_all("div", class_="WB_feed_handle")  # 获取微博信息父节点
        weibomessagecontents = weibomessages[0].find_all("a", class_="S_txt2")  #获取用于显示微博信息的节点(包括转发,评论,点赞数量)
        for weibomessagecontent in weibomessagecontents[1:]:                    #分别获取信息
            contents = weibomessagecontent.find_all("em")
            file.write(contents[1].text+"  ")
    file.close()
    print("成功存储一个页面的微博")
    return weibonum


def getpageurl(url,num):
    '''
    根据一个用户的第一页获取后续的url
    http://www.weibo.com/u/1858002662?c=spr_sinamkt_buy_hyww_weibo_p113&is_hot=1#1496336038914
    http://www.weibo.com/u/1858002662?is_search=0&visible=0&is_hot=1&is_tag=0&profile_ftype=1&page=2#feedtop

    http://weibo.com/leehom?refer_flag=1005055013_&is_all=1
    http://weibo.com/leehom?is_search=0&visible=0&is_all=1&is_tag=0&profile_ftype=1&page=2#feedtop
    通过分析指导,page应该是表示的页面,is_all和is_hot应该对应的是热门微博和全部微博
    '''
    preurl = url.split("?")
    preurl = preurl[0]
    pageurl = preurl+"?is_search=0&visible=0&is_all=1&is_tag=0&profile_ftype=1&page="+str(num)+"#feedtop"
    return pageurl

def spider(url,username,password):
    num = 0;
    browser = login("http://weibo.com/login.php",username,password)
    print("开始获取第1页的微博")
    html = getweibohtml(browser,url)
    file = open("f:\\xuanzi.txt","a",encoding="utf-8")
    user = getusermessage(html)
    for key in user.keys():
        file.write(key+":"+user[key]+"\n")
    file.close()
    num += getweibo("f:\\xuanzi.txt",html)
    print("获取第1页的微博成功")
    page = 1;
    while True:
        page+=1
        pageurl = getpageurl(url,page)
        print(pageurl)
        html = getweibohtml(browser, pageurl)
        if has_source(html):
            print("开始获取第"+str(page)+"页的微博")
            num += getweibo("f:\\xuanzi.txt",html)
        else:
            return
    return num

if __name__ =="__main__":

    #browser = login("http://weibo.com/login.php","15271183269","f43312626")

    '''
    for cookie in cookies:
        if cookie["name"] == "_s_tentry":
            log_cookie = cookie
            break
    '''
    '''
    getweibohtml("http://www.weibo.com/u/1858002662?is_search=0&visible=0&is_tag=0&profile_ftype=1&page=3&c=spr_sinamkt_buy_hyww_weibo_t113&is_all=1", browser)
    '''
    #print(has_source(browser,"http://www.weibo.com/u/1858002662?is_search=0&visible=0&is_tag=0&profile_ftype=1&page=21&c=spr_sinamkt_buy_hyww_weibo_t113&is_all=1"))
    #file = open("f:\\test5.html","rb").read()
    #html = file.decode("utf-8","ignore")
    #getweibo(html)

    #url = getpageurl("http://weibo.com/dasima315?sudaref=passport.weibo.com&is_all=1", 4)
    #print(url)
    #num = spider("http://www.weibo.com/u/1858002662?c=spr_sinamkt_buy_hyww_weibo_p113&is_hot=1", "15271183269", "f43312626")
    #print("一共获取"+str(num)+"条微博")

    spider("http://www.weibo.com/u/1858002662?c=spr_sinamkt_buy_hyww_weibo_p113&is_hot=1","15271183269","f43312626")
轩子局二兔的微博一共有21页,932条,以下是一部分爬取到的文件内容
姓名:轩子巨2兔
头像:http://tvax3.sinaimg.cn/crop.9.0.493.493.180/6ebedee6ly8ffq59vzv9qj20e80dpaag.jpg
认证:斗鱼直播平台签约主播
关注:293
粉丝:503619
微博:932


第1条微博内容是:
庆祝微博40万关注~转发这条骚气的微博,抽5人送出100元红包加一段私人定制音频~​​​​
http://wx3.sinaimg.cn/orj360/6ebedee6gy1feecnoofjvg20ap07ikjr.gif
4333  1810  3644  
第2条微博内容是:
来斗鱼快两个月了,昨夜斗鱼粉丝破了100万。黑粉很失望,他们竭尽全力却无法阻止。不膨胀,继续努力做好声音!为回馈百万轩子大军,抽5人送出100元红包和一段专属音频,转发即可,截止至3月25日24点。​​​​
http://wx2.sinaimg.cn/thumb150/6ebedee6gy1fdve8bakcpj20sf0kuara.jpg
http://wx1.sinaimg.cn/thumb150/6ebedee6gy1fdve8jbtjwj20sf0kudz7.jpg
4431  1768  3184  
第3条微博内容是:
“不知尬舞”​​​​
http://wx2.sinaimg.cn/thumb150/6ebedee6gy1fdir07mn9jj21kw23ungz.jpg
http://wx3.sinaimg.cn/thumb150/6ebedee6gy1fdir0akk9vj21kw22ekad.jpg
http://wx2.sinaimg.cn/thumb150/6ebedee6gy1fdir0ca1xaj21kw23ugzt.jpg
http://wx1.sinaimg.cn/thumb150/6ebedee6gy1fdir03x5dhj20k00ci77i.jpg
256  1281  5533  
第4条微博内容是:
这次斗鱼的美食节目因故取消了,但不影响真爱粉的福利。转发抽5人送100网费​​​​
http://wx2.sinaimg.cn/thumb150/6ebedee6gy1ff8qkcg02sj21be0qodn4.jpg
http://wx2.sinaimg.cn/thumb150/6ebedee6gy1ff8qkfkf19j21be0qo47a.jpg
http://wx2.sinaimg.cn/thumb150/6ebedee6gy1ff8qkk6zojj20qo1bedna.jpg
http://wx2.sinaimg.cn/thumb150/6ebedee6gy1ff8qky81l8j20qo1be10q.jpg
http://wx1.sinaimg.cn/thumb150/6ebedee6gy1ff8qkh1k32j21be0qoaiu.jpg
http://wx4.sinaimg.cn/thumb150/6ebedee6gy1ff8qllalw1j222o160njp.jpg
http://wx3.sinaimg.cn/thumb150/6ebedee6gy1ff8qkil677j21be0qoqb6.jpg
http://wx2.sinaimg.cn/thumb150/6ebedee6gy1ff8qkwcdmej21be0qojy6.jpg
http://wx1.sinaimg.cn/thumb150/6ebedee6gy1ff8qlb89d1j216022ox1n.jpg
1929  1118  3457  
第5条微博内容是:
小二,上硬菜​​​​
http://wx2.sinaimg.cn/thumb150/6ebedee6ly1ff78nnsqp8j20fa0r8amd.jpg
http://wx4.sinaimg.cn/thumb150/6ebedee6ly1ff78np27tqj20fg0r8gzm.jpg
http://wx1.sinaimg.cn/thumb150/6ebedee6ly1ff78nqthtzj20pz1ai7wh.jpg
http://wx4.sinaimg.cn/thumb150/6ebedee6ly1ff78ns0smvj20fe0r8k4l.jpg
http://wx3.sinaimg.cn/thumb150/6ebedee6ly1ff78nt7qxvj20fb0r87ij.jpg
http://wx3.sinaimg.cn/thumb150/6ebedee6ly1ff78nulu72j20kl0yk4j8.jpg
815  1372  4269  
第6条微博内容是:
我是俏皮猫女郎​​​​
http://wx1.sinaimg.cn/thumb150/6ebedee6ly1ffn14hn37qj21w02ioqv5.jpg
http://wx3.sinaimg.cn/thumb150/6ebedee6ly1ffn14mcya9j21w02ioqv5.jpg
http://wx4.sinaimg.cn/thumb150/6ebedee6ly1ffn14qb0fjj21w02ioe81.jpg
http://wx4.sinaimg.cn/thumb150/6ebedee6ly1ffn14u8jluj22io1w0b29.jpg
http://wx4.sinaimg.cn/thumb150/6ebedee6ly1ffn14y0q7fj22io1w0b29.jpg
413  1179  4193  
第7条微博内容是:
不知火舞第二弹。(小剧场剧本、情感问题征稿,邮箱[email protected])​​​​
http://wx3.sinaimg.cn/thumb150/6ebedee6gy1fdt5ta5tusj20xr190wmf.jpg
http://wx1.sinaimg.cn/thumb150/6ebedee6gy1fdt5tch8qmj20xr190aib.jpg
207  1265  4124  
第8条微博内容是:
王者荣耀.妲己cos第一弹​​​​
http://wx3.sinaimg.cn/thumb150/6ebedee6gy1fe1a9fiwnnj21w02ionpl.jpg
http://wx3.sinaimg.cn/thumb150/6ebedee6gy1fe1a8xn3zpj20qo0zk0yk.jpg
http://wx1.sinaimg.cn/thumb150/6ebedee6gy1fe1a9hc60oj20zk0qote9.jpg
159  936  3684  
第9条微博内容是:
包子可爱吗​​​​
http://wx4.sinaimg.cn/thumb150/6ebedee6ly1ff08cqq6upj216022o1kx.jpg
http://wx3.sinaimg.cn/thumb150/6ebedee6ly1ff08crpnw0j216022onnv.jpg
http://wx1.sinaimg.cn/thumb150/6ebedee6ly1ff08czm47oj23402c0b2e.jpg
75  1079  3008  
第10条微博内容是:
妲己第二弹愚人节快乐!​​​​
http://wx1.sinaimg.cn/thumb150/6ebedee6ly1fe6iuhxa24j20qo0zk0yl.jpg
http://wx4.sinaimg.cn/thumb150/6ebedee6ly1fe6iu4w2u3j21w02iox6v.jpg
http://wx4.sinaimg.cn/thumb150/6ebedee6ly1fe6itjy35tj20pm0zkwgv.jpg
92  627  3175  
第11条微博内容是:
上海的小伙伴猜猜我在哪​​​​
http://wx4.sinaimg.cn/orj360/6ebedee6ly1fe9kelwnnoj20k00zk0w7.jpg
15  628  3225  
第12条微博内容是:
不穿丝袜会死星人​​​​
http://wx1.sinaimg.cn/thumb150/6ebedee6ly1ffi0e6bgfyj21k1160qn4.jpg
http://wx4.sinaimg.cn/thumb150/6ebedee6ly1ffi0e97arzj222o1604qp.jpg
http://wx1.sinaimg.cn/thumb150/6ebedee6ly1ffi0efepbkj222o1607wh.jpg
http://wx4.sinaimg.cn/thumb150/6ebedee6ly1ffi0ekex7sj222o1607wh.jpg
61  562  3079  
第13条微博内容是:
我觉得这个吊带好看,另外谁的弟弟有多动症的话可以来听我的直播​​​​
http://wx3.sinaimg.cn/thumb150/6ebedee6ly1ffwzs52a9fj21bf0qo465.jpg
http://wx3.sinaimg.cn/thumb150/6ebedee6ly1ffwzs4jfebj20qo1bfai7.jpg
http://wx1.sinaimg.cn/thumb150/6ebedee6ly1ffwzs5gq92j21bf0qoqcv.jpg
61  599  2832  


你可能感兴趣的:(爬虫,python,新浪微博,微博,模拟登陆,微博爬虫)