zoukankan      html  css  js  c++  java
  • C#爬取微博文字、图片、视频(不使用Cookie)

    前两天在网上偶然看到一个大佬OmegaXYZ写的文章,Python爬取微博文字与图片(不使用Cookie) 

    于是就心血来潮,顺手撸一个C#版本的。

    其实原理也很简单,现在网上大多数版本都需要Cookie来获取微博数据。但是微博之前不是出了PWA版本嘛,就是通过这个版本,可以不用Cookie,来顺利获取微博数据。

    关于使用Cookie与不使用Cookie的区别,dataabc大佬也有说明,下面是原文引用

    对于大部分微博用户,不添加cookie也可以获取其用户信息和大部分微博,不同的微博获取比例不同。以2020年1月2日迪丽热巴的微博为例,
    此时她共有1085条微博,在不添加cookie的情况下,可以获取到1026条微博,大约占全部微博的94.56%,而在添加cookie后,可以获取全部微博。
    其他用户类似,大部分都可以在不添加cookie的情况下获取到90%以上的微博,在添加cookie后可以获取全部微博。
    具体原因是,大部分微博内容都可以在移动版匿名获取,少量微博需要用户登录才可以获取,所以这部分微博在不添加cookie时是无法获取的。
    有少部分微博用户,不添加cookie可以获取其微博,无法获取其用户信息。对于这种情况,要想获取其用户信息,是需要cookie的。

    dataabc大佬,也是用万能的Python写了两个版本,一个是需要Cookie,一个是不需要Cookie的。

    而且使用方法写的非常详细。有需要的可以去Github膜拜。

    这里贴一下我亲自运行的结果:

    而开头提到OmegaXYZ大佬,也是在他自己的版本上更上一层,给Python代码加上了GUI界面,更适合大众小白用户。

    原文地址:python微博爬虫GUI程序

    好了,介绍完大佬们写的作品,接下来就说一下我自己的C#版本吧。

    由于我在爬虫领域属于纯小白,一窍不通,所以并不懂什么爬虫(Spider)、反爬虫(Anti-Spider)、反反爬虫(Anti-Anti-Spider)。

    不过在爬虫与反爬虫的斗争中,爬虫一定会胜利的,因为爬虫会进化为和真实用户一模一样的行为。

    接下载我写的代码,是没有加入反反爬虫的,建议一跑起来,就立即终止,或者,加入一个Task.Delay(1000)之类的延时。

    不要爬取的太快,容易被微博屏蔽ip!!!

    不要爬取的太快,容易被微博屏蔽ip!!!

    不要爬取的太快,容易被微博屏蔽ip!!!

    即使被屏蔽也别慌,过一段时间就会恢复。

    1. 获取用户的uid,构建基础url

    uid即微博用户的唯一标识id,具体如何获取uid,可以查看前面二位大佬写的教程,这并不是本文的重点。

    基础url是指我们通过这个,可以获取微博用户的基本信息,以及一个非常重要的字段:containerid

    只有通过containerid才可以获取用户发的微博。

    一个完整的实例Url:

    string strBaseUrl = "https://m.weibo.cn/api/container/getIndex?type=uid&value=1197191492";

    2.通过HttpClient获取containerid

    通过HttpClient,把strBaseUrl和uid拼接起来,我们就可以得到返回的json数据。

    而我们需要的containerid就是在 res?.data?.tabsInfo?.tabs 下面。

                var res = await HttpHelper.GetAsync<UserSummary>(strBaseUrl);
                if(res != null && res?.ok == 1)
                {
                    if(res?.data?.tabsInfo?.tabs != null)
                    {
                        foreach(var item in res?.data?.tabsInfo?.tabs)
                            if(item.tab_type == "weibo")
                            {
                                strContainerId = item.containerid;
                                break;
                            }
                    }
                }

    3. 拼接基础url、containerid、page获取分页微博信息。

    拼接上面的参数,一个完整的示例:

    https://m.weibo.cn/api/container/getIndex?type=uid&value=1197191492&containerid=1076031197191492&page=1

    这里我通过自己的理解区分了三种微博类型:

    ①包含图片:

        判断 home?.data?.cards[j].mblog.pics != null

    ②包含视频:

        判断 home?.data?.cards[j].mblog.page_info != null && home?.data?.cards[j].mblog.page_info.type == "video"

    ③文字:

       不是①和②的

    不过应该还有其他的类型,我还没仔细分析。

    C#代码:

    string strWeiboUrl = strBaseUrl + "&containerid=" + strContainerId + "&page=";
                int i = 1;
                while(true)
                {
                    var home = await HttpHelper.GetAsync<UserHome>(strWeiboUrl + i.ToString());
                    if (home != null && home?.ok == 1 && home?.data != null && home?.data?.cards?.Count > 0)
                    {
                        Debug.WriteLine("---第" + i + "页---");
    
                        for (int j = 0; j <= home?.data?.cards.Count - 1; j++)
                        {
                            if(home?.data?.cards[j].card_type == 9)
                            {
                                Debug.WriteLine("" + (j + 1) + "条微博---");
                                Debug.WriteLine("微博原始地址:" + home?.data?.cards[j].scheme);
                                if(home?.data?.cards[j].mblog != null)
                                {
                                    Debug.WriteLine("发布日期:" + home?.data?.cards[j].mblog.created_at
                                        + ";转发数:" + home?.data?.cards[j].mblog.reposts_count
                                        + ";评论数:" + home?.data?.cards[j].mblog.comments_count
                                        + ";点赞数:" + home?.data?.cards[j].mblog.attitudes_count);
                                    if (!string.IsNullOrEmpty(home?.data?.cards[j].mblog.source))
                                        Debug.WriteLine("来自:" + home?.data?.cards[j].mblog.source);
                                    Debug.WriteLine("微博内容:" + home?.data?.cards[j].mblog.text);
                                    if(home?.data?.cards[j].mblog.pics != null)
                                    {
                                        Debug.WriteLine("微博类型:picture");
                                        foreach (var item in home?.data?.cards[j].mblog.pics)
                                            Debug.WriteLine(item.large.url);
                                    }
                                    else if(home?.data?.cards[j].mblog.page_info != null && home?.data?.cards[j].mblog.page_info.type == "video")
                                    {
                                        Debug.WriteLine("微博类型:" + home?.data?.cards[j].mblog.page_info.type);
                                        Debug.WriteLine(home?.data?.cards[j].mblog.page_info.media_info.mp4_hd_url);
                                    }
                                    else
                                    {
                                        Debug.WriteLine("微博类型:text");
                                    }
    
                                    //转发的还是原创的
                                    if(home?.data?.cards[j].mblog.retweeted_status == null)
                                    {
                                        Debug.WriteLine("原创的微博");
                                    }
                                    else
                                    {
                                        Debug.WriteLine("转发的微博");
                                        Debug.WriteLine("原文作者:" + home?.data?.cards[j].mblog.retweeted_status.user.screen_name);
                                        Debug.WriteLine("原文内容:" + home?.data?.cards[j].mblog.retweeted_status.text);
                                    }
                                }
                                Debug.WriteLine("");
                            }
                        }
    
                        i++;
                        Debug.WriteLine("");
                        Debug.WriteLine("");
                        Debug.WriteLine("");
                    }
                    else
                        break;
                }

    4. 最终效果

    运行后,记得赶快停掉,别爬太多数据,容易被封。

    后续我会研究如使用反反爬虫机制,防止被封。

  • 相关阅读:
    2019年面试题1
    面试题
    vsftp多个用户公享同一个文件,但是权限不同
    centos7搭建ftp
    安装v2ra y
    centos7安装lamp
    日升昌面试题
    一些插件
    面试被怼集(字节跳动篇)
    TOMCAT原理详解及请求过程(转载)
  • 原文地址:https://www.cnblogs.com/hupo376787/p/12434841.html
Copyright © 2011-2022 走看看