美文网首页
如何利用 C# 爬取「猫眼电影:最受期待榜」及对应影片信息!

如何利用 C# 爬取「猫眼电影:最受期待榜」及对应影片信息!

作者: 老马的程序人生 | 来源:发表于2019-03-07 15:56 被阅读0次

“道路千万条,安全第一条!行车不规范,亲人两行泪!”

这句在影片“流浪地球”中不断重复的话语已经被大家所熟知。为了行车的安全,我们需要遵守规范,提前规划。同样,在快节奏生活中的我们,也需要抽出时间来规划自己的娱乐。最简单的规划莫过于周末的时候,看看有没有喜欢的电影上映,以便安排自己的娱乐时间。

今天,我就带着大家来爬取“猫眼电影:最受期待榜”,通过这份榜单,我们可以看到最近这段时间有哪些电影即将上映,这些电影有多少人期待观影。通过这些数据,来辅助我们规划娱乐时间。


首先,我们来看看“猫眼电影:最受期待榜”的原网页,网页地址为:

https://maoyan.com/board/6?offset=0

原网页 第一页

我们选择“下一页”发现,网址发生了变化,

https://maoyan.com/board/6?offset=10

原网页 下一页

接着,选择“下一页”,网址变为:

https://maoyan.com/board/6?offset=20

通过观察,我们可以发现爬取网页地址的变化规律,即参数offset以 10 为步长递增。

爬取的网址有了,我们来看看网页的源码:

榜单第一页对应的源代码

我们发现,所有数据都存储在 <dd> 标签内,主演、上映时间、本月新增想看人数、总想看人数存储在 <p> 标签内。

这里值得注意的是,猫眼电影采取了反爬虫机制对“本月新增想看人数”、“总想看人数”进行了加密处理。我们查找 stonefont 类,发现 猫眼电影 使用 font-face 定义字符集,并通过 unicode 去映射展示,所以我们在网页上看到的是数字,但是在源码中看到的却是别的字符。

font-face 字体编码

如何破解猫眼电影的反爬虫机制呢?我会在后面专门写一篇图文来介绍。这里暂且搁置一下。

影片详细信息展示的网址,可通过 <a> 标签的 href 属性获取,如上图对应影片“惊奇队长”的网址为:

https://maoyan.com/films/341139

影片信息

我们查看该网页对应的源代码,发现影片的类型存储在 li.ellipsis 类中,影片的简介存储在 dra 类中。

影片网页对应代码

通过以上的分析,只要我们得到相应网页的HTML DOM TREE,使用选择器找到对应位置,就能提取出相应的数据。获取HTML DOM TREE,我推荐一套开源类库 Jumony,可以在 Github 上下载。下载地址为:

https://github.com/Ivony/Jumony

Jumony下载

这里对 Jumony 就不做过多介绍了,要是大家感兴趣,可以在图文下方留言,我后面再写几篇图文来介绍这个工具。


到此为止,网页分析、所用工具已经介绍完了,下面介绍一下我们写的代码。

1.定义存储电影的结构 Film。包含排名、名称、类型、本月新增想看人数、总想看人数、主演、上映时间、简介等。

/// <summary>
/// 表示电影的类
/// </summary>
public class Film
{
    /// <summary>
    /// 获取或设置 排名
    /// </summary>
    public int Num { get; set; }
    /// <summary>
    /// 获取或设置 名称
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// 获取或设置 类型
    /// </summary>
    public string Type { get; set; }
    /// <summary>
    /// 获取或设置 本月新增想看
    /// </summary>
    public string NewWatcher { get; set; }
    /// <summary>
    /// 获取或设置 总想看
    /// </summary>
    public string TotalWatcher { get; set; }
    /// <summary>
    /// 获取或设置 主演
    /// </summary>
    public string Actor { get; set; }
    /// <summary>
    /// 获取或设置 上映时间
    /// </summary>
    public string Time { get; set; }
    /// <summary>
    /// 获取或设置 简介
    /// </summary>
    public string Introduction { get; set; }
    /// <summary>
    /// Markdown格式化输出
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        string str = Environment.NewLine
                + "---" + Environment.NewLine
                + "## Top" + Num.ToString().PadLeft(2, '0') + " <br>"
                + Name + Environment.NewLine
                + "- 类型:" + Type + Environment.NewLine
                + "- 主演:" + Actor + Environment.NewLine
                + "- 上映时间:" + Time + Environment.NewLine
                + "- 本月新增想看:<span style='color:#FF8F00'><b>" 
                + NewWatcher
                + "</b></span>" + Environment.NewLine
                + "- 总想看:<span style='color:#757575'><b>" 
                + TotalWatcher
                + "</b></span>" + Environment.NewLine
                + "- 剧情简介:" + Introduction 
                + Environment.NewLine;
        return str;
    }
}

2. 根据URL得到对应的HTML DOM TREE

offset:对应要抓取「猫眼电影:最受期待榜」哪一页的数据,间隔为10。

public static IHtmlDocument GetHtmlDocument(string url, int offset)
{
    IHtmlDocument document;
    try
    {
        document = new JumonyParser().LoadDocument(url 、
                + "?offset=" + offset);
    }
    catch
    {
        document = null;
    }
    return document;
}

3. 得到「猫眼电影:最受期待榜」的数据。

public static List<Film> GetFilmsExpect(int offset)
{
    List<Film> result = new List<Film>();
    //最受期待榜
    string url = "https://maoyan.com/board/6"; 
    IHtmlDocument doc = GetHtmlDocument(url, offset);

    if (doc == null)
        return result;

    List<IHtmlElement> lists = doc.Find("dd").ToList();
    for (int i = 0; i < lists.Count; i++)
    {
        List<IHtmlElement> infor = lists[i].Find("p").ToList();
        Film item = new Film();
        //排名
        item.Num = i + 1; 
        //演员
        item.Actor = infor[1].InnerHtml().Trim().Remove(0, 3); 
        //上映时间
        item.Time = infor[2].InnerHtml().Trim().Remove(0, 5); 
        
        string dw = infor[3].InnerHtml().Trim();
        dw = dw.Remove(0, dw.Length - 1); //单位
        
        List<IHtmlElement> p = infor[3].Find(".stonefont").ToList();
        //加密的新增想看人数
        string people = p[0].InnerHtml().Trim(); 
        item.NewWatcher = GetPeople(people) + dw; //解密的新增想看人数
        
        dw = infor[4].InnerHtml().Trim();
        dw = dw.Remove(0, dw.Length - 1); //单位
        p = infor[4].Find(".stonefont").ToList();
        people = p[0].InnerHtml().Trim(); //加密的总想看人数
        item.TotalWatcher = GetPeople(people) + dw; //解密的总想看人数

        IHtmlElement a = infor[0].Find("a").ToList()[0]; //获取影片url
        item.Name = a.InnerHtml().Trim(); //名称
        
        url = "https://maoyan.com" + a.Attribute("href").AttributeValue;
        IHtmlDocument temp = GetHtmlDocument(url);
        List<IHtmlElement> t = temp.Find("li.ellipsis").ToList();
        item.Type = t[0].InnerHtml(); //类型
        
        List<IHtmlElement> b = temp.Find(".dra").ToList();
        item.Introduction = b[0].InnerHtml(); //介绍
        result.Add(item);
    }
    return result;
}

4. 得到 Markdown 格式化输出的「猫眼电影:最受期待榜」。

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

5. 渲染 Markdown 格式化输出的结果。

渲染结果

最后,我们再来总结一下。

通过对“猫眼电影:最受期待榜”的网页分析,我们确定了爬取网页的 URL 地址结构,利用 Jumony 开源类库得到该网页的 HTML DOM TREE,使用选择器得到对应的电影数据集合,最后格式化输出为 Markdwon 文本。经过渲染可以构成我们每周五推荐的 猫眼电影:「即将上映、最受期待」榜 的图文内容。(这里剩下 如何破解猫眼电影的“字体反爬策略”,后面再写一篇图文详细介绍。)

怎么样,是不是很有趣。大家来试试看,今天就到这里吧,See You!


推荐阅读

相关文章

网友评论

      本文标题:如何利用 C# 爬取「猫眼电影:最受期待榜」及对应影片信息!

      本文链接:https://www.haomeiwen.com/subject/bpwcpqtx.html