如何利用 C# 爬取「猫眼电影专业版:票房」数据!

在现代生活中,看电影已经成为大家的一种休闲方式。

前几天,我们介绍了 如何利用 C# 爬取「猫眼电影:热映口碑榜」及对应影片信息!,通过这份“热映口碑”榜单,我们可以看到大家对当前热播电影的评价,为我们选择所要观看的电影提供了辅助支持。但仅有这份榜单还是不够的,我们还想知道这些热映电影更详细的数据,比如:“实时票房”、“累积票房”、“票房占比”、“排片占比”、“上座率”等等,以便更好的选择出一部令自己满意的影片,更好的分配自己的娱乐时间。


下面,我就带大家从“猫眼专业版”的网站上来爬取以上的数据。

首先,我们浏览一下“猫眼专业版”的网页,网址如下(选择2019年03月01日的数据):

https://piaofang.maoyan.com/dashboard?date=2019-03-01

原网页

对应的源代码如下:

源代码

注:如果需要选择2019年03月02日的数据,只需要调整URL中的date参数值,把2019-03-01换为2019-03-02即可。

https://piaofang.maoyan.com/dashboard?date=2019-03-02

其次,我们从源代码中发现<div class="movielist"></div>部分,并不包含数据,初步断定该网页采用了“前后端分离”的开发方式。故打开浏览器的控制台,发现了确实从服务器请求的JSON数据,请求网址如下:

https://box.maoyan.com/promovie/api/box/second.json?beginDate=20190301

Network

对应的JSON数据如下:

Json数据

我们想要的数据包含在list数组中,如下图所示:

所需数据

这样,我们就找到了所要获取的JSON数据。


怎样处理JSON数据呢?我这里使用了一套处理JSON数据的开源类库Json.NET,通过这套类库可以把得到的JSON数据反序列化成对应的类型。Json.NET的 Git 网址如下:

https://github.com/JamesNK/Newtonsoft.Json

git

有需要的同学可以到 Git 上下载源码,这里就不过多介绍这个开源类库了。如果对大家对Json.NET感兴趣可以在图文下面留言,我会另外写一些图文详细介绍这套类库的源码以及具体应用。


到此为止,网页的分析部分就介绍完了,下面我们来看具体的代码部分:

1. 定义存储电影的结构Film。包括“编号、名称、实时票房、总票房、票房占比、排片占比、上座率”等等。

public class Film
{
    /// <summary>
    /// 获取或设置 编号
    /// </summary>
    public int Num { get; set; }
    
    /// <summary>
    /// 获取或设置 名称
    /// </summary>
    public string MovieName { get; set; }
    
    /// <summary>
    /// 获取或设置 实时票房
    /// </summary>
    public string BoxInfo { get; set; }

    /// <summary>
    /// 获取或设置 票房占比
    /// </summary>
    public string BoxRate { get; set; }
    
    /// <summary>
    /// 获取或设置 排片占比
    /// </summary>
    public string ShowRate { get; set; }

    /// <summary>
    /// 获取或设置 总票房
    /// </summary>
    public string SumBoxInfo { get; set; }

    /// <summary>
    /// 获取或设置 上座率
    /// </summary>
    public string AvgSeatView { get; set; }

    /// <summary>
    /// Markdown 格式化输出
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        string str = Environment.NewLine
                + "---" + Environment.NewLine
                + "## Top" + Num.ToString().PadLeft(2, '0') + " <br>"
                + MovieName + Environment.NewLine
                + "- 实时票房:<span style='color:#E53935'><b>" + BoxInfo
                + "</b></span>" + Environment.NewLine
                + "- 票房占比:<span style='color:#E53935'><b>" + BoxRate
                + "</b></span>" + Environment.NewLine
                + "- 排片占比:<span style='color:#E53935'><b>" + ShowRate
                + "</b></span>" + Environment.NewLine
                + "- 上座率:<span style='color:#E53935'><b>" + AvgSeatView
                + "</b></span>" + Environment.NewLine
                + "- 总票房:<span style='color:#757575'><b>" + SumBoxInfo
                + "</b></span>" + Environment.NewLine;
        return str;
    }
}

2. 根据URL得到包含电影数据的JSON

public static string GetFilmsJson(string url)
{
    //1. HttpWebRequest 发送HTTP数据
    HttpWebRequest webRequest = WebRequest.Create(url) as HttpWebRequest;
    if (webRequest == null)
        return string.Empty;
        
    webRequest.Method = "GET";
    webRequest.ContentType = "application/json;charset=utf-8";
    webRequest.Accept = "*/*";

    try
    {
        string json;
        using (HttpWebResponse webResponse = (HttpWebResponse) webRequest.GetResponse())
        //2.HttpWebResponse 接收HTTP数据
        {
            Stream st = webResponse.GetResponseStream(); 

            if (st == null)
                return string.Empty;

            using (StreamReader reader = new StreamReader(st, Encoding.UTF8)) 
            {
                json = reader.ReadToEnd(); 
                reader.Close();
                webResponse.Close();
            }
        }
        return json;
    }
    catch
    {
        return string.Empty;
    }
}

3. 为反序列化该JSON定义对应的结构。

这块定义的结构与JSON的格式相对应,可以结合上面JSON数据的图来看。

private class Item
{
    /// <summary>
    /// 上座率
    /// </summary>
    public string avgSeatView { get; set; }
    /// <summary>
    /// 实时票房
    /// </summary>
    public string boxInfo { get; set; }
    /// <summary>
    /// 票房占比
    /// </summary>
    public string boxRate { get; set; }
    /// <summary>
    /// 排片占比
    /// </summary>
    public string showRate { get; set; }
    /// <summary>
    /// 名称
    /// </summary>
    public string movieName { get; set; }
    /// <summary>
    /// 总票房
    /// </summary>
    public string sumBoxInfo { get; set; }
}

private class Data
{
    public List<Item> list;
}

private class JsonFilm
{
    public Data data { get; set; }
}

4. 反序列化JSON到对应的类中,并得到存储电影数据的链表。

public static List<Film> GetFilmsMaoYanTicket(string date)
{
    List<Film> result = new List<Film>();

    string url = @"https://box.maoyan.com/promovie/api/box/"
            +@"second.json?beginDate="
            + date;

    //通过JSON的方式来实现
    string json = GetFilmsJson(url);
    
    StringReader sr = new StringReader(json);
    JsonTextReader jsonReader = new JsonTextReader(sr);
    JsonSerializer serializer = new JsonSerializer();
    JsonFilm r = serializer.Deserialize<JsonFilm>(jsonReader);

    List<Item> lst = r.data.list;
    for (int i = 0, len = lst.Count; i < len; i++)
    {
        Film film = new Film();
        film.Num = i + 1;
        film.MovieName = lst[i].movieName;
        film.AvgSeatView = lst[i].avgSeatView;
        film.BoxInfo = lst[i].boxInfo + "万";
        film.BoxRate = lst[i].boxRate;
        film.ShowRate = lst[i].showRate;
        film.SumBoxInfo = lst[i].sumBoxInfo;
        result.Add(film);
    }
    return result;
}

5. Markdown 格式化输出爬取的“猫眼电影专业版:票房”的数据。

private string GetReportReputation(List<Film> lst)
{
    string result = Environment.NewLine;
    for (int i = 0; i < lst.Count; i++)
    {
        result += lst[i].ToString() + Environment.NewLine;
    }
    return result;
}

6. 把Markdown格式的文本渲染成HTML格式的文本。

渲染文本

以上我们分析了“猫眼电影专业版”的网页,得知该网页采取了前后端分离的开发方式,于是我们先得到了存储信息的JSON数据,并利用Json.net类库对其反序列化,得到对应的类,从而完成了整个网页的爬取过程。

是不是很有趣,大家也来试试吧!今天就到这里了,See You!


参考图文:

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容