如何利用 C# + Python 破解猫眼电影的反爬虫机制?

news/2024/7/5 2:02:20

在 如何利用 C# 爬取「猫眼电影:最受期待榜」及对应影片信息! 这篇图文中可以看到猫眼电影对“本月新增想看人数” 和 “总想看人数”进行了字符集加密。

字体编码

在 如何利用 C# 爬取「猫眼电影:国内票房榜」及对应影片信息! 这篇图文中也可以看到猫眼电影对“实时票房” 和 “总票房”进行了字符集加密。

字体编码

破解这种利用字符集加密的反爬虫机制,需要建立映射关系表,找到每个字符对应的真实数字即可。怎么做呢?

我们 首先 需要把对应的字符集下载到本地。

stonefont类

然后,把该字符集转换成XML文件。由于 Python 中有 TTFont 指令可以直接使用,于是把转换的功能用 Python 来写并用 pyinstaller 指令打包成 EXE 文件,通过 C# 语言进行调用即可。

imports sys
from fontTools.ttLib import TTFontif __name__ =='__main__'font1 = TTFont(str(sys.argv[1]))font1.saveXML(str(sys.argv[2]))

打包main.py文件的代码:

pyinstaller -F main.py

生成的 XML 文件如下:

图形信息

接着,建立映射关系表,把TTGlyph namecountour和真实的数据对应起来。这个不能自动化只能把网页上的数字与源代码中的字符对应,在通过源代码中的字符与这个XML中的 TTGlyph name对应。

映射关系

最后,可以通过加载这份映射表来破解猫眼电影的反爬虫机制。即我先在内存中加载这份映射表,每个字体的图形名称TTGlyph name在刷新后是变化的,但图形信息countour是不会变化的,所以可以先通过图形名称找到图形信息,在通过这份映射表找到对应的真实数字。


以上详细的介绍了破解猫眼电影反爬虫机制的方法,下面我们来写具体的代码。

1. 构造字体图形的结构 FontGlyph

public class FontGlyph
{/// <summary>/// 图形名称/// </summary>public string Name { get; set; }/// <summary>/// 图形数据/// </summary>public string Glyph { get; set; }/// <summary>/// 图形值/// </summary>public int Value { get; set; } = -1;
}

2. 获取字体 WOFF 文件的存储地址

private static string GetWoffUrl(string str)
{int end = str.IndexOf(@"') format('woff')", StringComparison.Ordinal);int start = str.LastIndexOf("//vfile.meituan.net", StringComparison.Ordinal);string url = str.Substring(start, end - start);return "http:" + url;
}

3. 下载字体 WOFF 文件到本地

private static string Download(string url)
{int index = url.LastIndexOf("/", StringComparison.Ordinal);string fileName = @".\font\" + url.Substring(index + 1);HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;if (request == null)return string.Empty;HttpWebResponse response = request.GetResponse() as HttpWebResponse;if (response == null)return string.Empty;Stream reponseStream = response.GetResponseStream();if (reponseStream == null)return string.Empty;Stream stream = new FileStream(fileName, FileMode.Create);byte[] bArr = new byte[1024];int size = reponseStream.Read(bArr, 0, bArr.Length);while (size > 0){stream.Write(bArr, 0, size);size = reponseStream.Read(bArr, 0, bArr.Length);}stream.Close();reponseStream.Close();return fileName;
}

4. 转换字体 WOFF 文件为XML文件

private static string TransXml(string fileName)
{string xml = @".\font\" + Path.GetFileNameWithoutExtension(fileName) + ".xml";Process p = new Process();p.StartInfo.FileName = @".\font\main.exe";p.StartInfo.UseShellExecute = false;p.StartInfo.RedirectStandardOutput = true;p.StartInfo.RedirectStandardInput = true;p.StartInfo.CreateNoWindow = true;p.StartInfo.Arguments = fileName + " " + xml;p.Start();p.WaitForExit();p.Close();return xml;
}

5. 根据 XML 文件获得字体图形文件列表 List<FontGlyph>

private static List<FontGlyph> GetXmlGlyf(string path)
{List<FontGlyph> result = new List<FontGlyph>();XmlDocument xmldoc = new XmlDocument();XmlReaderSettings settings = new XmlReaderSettings();settings.IgnoreComments = true;XmlReader reader = XmlReader.Create(path, settings);xmldoc.Load(reader);if (xmldoc.DocumentElement == null)return result;XmlNodeList nodeList = xmldoc.DocumentElement.ChildNodes;foreach (XmlNode node in nodeList){if (node.Name == "glyf"){XmlNodeList lst = node.ChildNodes;foreach (XmlNode n in lst){XmlElement xe = n as XmlElement;if (xe != null){if (string.IsNullOrEmpty(xe.InnerXml) == false){FontGlyph item = new FontGlyph();item.Name = xe.GetAttribute("name");item.Glyph = xe.InnerXml;item.Value = -1;result.Add(item);}}}}}return result;
}

6. 建立映射关系

private static int GetValue(string name)
{string[] str = new string[]{"uniF756", "uniED75", "uniF8F8", "uniF81A", "uniEE70", "uniECA0","uniEC6F", "uniE93B", "uniE9D3","uniF8B5"};for (int i = 0; i < str.Length; i++){if (str[i] == name)return i;}return -1;
}private static List<FontGlyph> GetFontGlyphList(string fileName)
{List<FontGlyph> lst = GetXmlGlyf(fileName);for (int i = 0, len = lst.Count; i < len; i++){lst[i].Value = GetValue(lst[i].Name);}return lst;
}

7. 解密算法

private static string Decrypt(string str, List<FontGlyph> lstModel, List<FontGlyph> lstCur)
{string result = string.Empty;string[] ss = str.Split(new char[] {'.'});string[] ss1 = ss[0].Split(new char[] {';'}); //处理整数部分for (int i = 0; i < ss1.Length; i++){if (string.IsNullOrEmpty(ss1[i]) == false){int d = GetIndex(ss1[i], lstCur);int v = GetValue(lstCur[d].Glyph, lstModel);result += v.ToString();}}if (ss.Length != 1) //处理小数部分{result += ".";string[] ss2 = ss[1].Split(new char[] {';'});for (int i = 0; i < ss2.Length; i++){if (string.IsNullOrEmpty(ss2[i]) == false){int d = GetIndex(ss2[i], lstCur);int v = GetValue(lstCur[d].Glyph, lstModel);result += v.ToString();}}}return result;
}private static int GetIndex(string str, List<FontGlyph> lstCur)
{for (int i = 0, len = lstCur.Count; i < len; i++){if (lstCur[i].Name.Contains(str.Substring(3).ToUpper()))return i;}return -1;
}private static int GetValue(string str, List<FontGlyph> lstModel)
{for (int i = 0, len = lstModel.Count; i < len; i++){if (lstModel[i].Glyph == str){return lstModel[i].Value;}}return -1;
}

8. 获取「猫眼电影:国内票房榜 及对应影片信息」修改后的代码

public static List<Film> GetFilmsTicket()
{List<Film> result = new List<Film>();string url = "https://maoyan.com/board/1"; //国内票房榜IHtmlDocument doc = GetHtmlDocument(url);if (doc == null)return result;List<FontGlyph> lstModel = GetFontGlyphList(@".\font\base.xml");List<IHtmlElement> woffStr = doc.Find("style").ToList();string tempUrl = GetWoffUrl(woffStr[0].InnerHtml());string fileNameWoff = Download(tempUrl);string fileNameXml = TransXml(fileNameWoff);List<FontGlyph> lstNew = GetXmlGlyf(fileNameXml);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; //排名string dw, ticket;List<IHtmlElement> s;if (infor.Count < 5){item.Time = infor[1].InnerHtml().Trim().Remove(0, 5); //上映时间dw = infor[2].InnerHtml().Trim();dw = dw.Remove(0, dw.Length - 1); //实时票房单位s = infor[2].Find(".stonefont").ToList();ticket = s[0].InnerHtml().Trim(); //加密的实时票房item.BoxInfo = Decrypt(ticket, lstModel, lstNew) + dw; //实时票房dw = infor[3].InnerHtml().Trim();dw = dw.Remove(0, dw.Length - 1); //总票房单位s = infor[3].Find(".stonefont").ToList();ticket = s[0].InnerHtml().Trim(); //加密的总票房item.SumBoxInfo = Decrypt(ticket, lstModel, lstNew) + dw; //总票房}else{item.Actor = infor[1].InnerHtml().Trim().Remove(0, 3); //演员item.Time = infor[2].InnerHtml().Trim().Remove(0, 5); //上映时间dw = infor[3].InnerHtml().Trim();dw = dw.Remove(0, dw.Length - 1); //实时票房单位s = infor[3].Find(".stonefont").ToList();ticket = s[0].InnerHtml().Trim(); //加密的实时票房item.BoxInfo = Decrypt(ticket, lstModel, lstNew) + dw; //实时票房dw = infor[4].InnerHtml().Trim();dw = dw.Remove(0, dw.Length - 1); //总票房单位s = infor[4].Find(".stonefont").ToList();ticket = s[0].InnerHtml().Trim(); //加密的总票房item.SumBoxInfo = Decrypt(ticket, lstModel, lstNew) + dw; //总票房}IHtmlElement a = infor[0].Find("a").ToList()[0]; //获取影片urlitem.MovieName = 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;
}

9. 获取「猫眼电影:最受期待榜及对应影片信息」修改后的代码

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<FontGlyph> lstModel = GetFontGlyphList(@".\font\base.xml");List<IHtmlElement> woffStr = doc.Find("style").ToList();string tempUrl = GetWoffUrl(woffStr[0].InnerHtml());string fileNameWoff = Download(tempUrl);string fileNameXml = TransXml(fileNameWoff);List<FontGlyph> lstNew = GetXmlGlyf(fileNameXml);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 = Decrypt(people, lstModel, lstNew) + 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 = Decrypt(people, lstModel, lstNew) + dw; //解密的总想看人数IHtmlElement a = infor[0].Find("a").ToList()[0]; //获取影片urlitem.MovieName = 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;
}

10. 输出结果

猫眼电影:国内票房榜 及对应影片信息

结果1

猫眼电影:最受期待榜及对应影片信息

结果2


到此为止,有关如何破解猫眼电影的反爬虫机制就全部介绍完了,破解这种反爬虫机制相对来说比较复杂。如果网站通过用户请求的 Headers 进行反爬虫或者通过限制同一IP短时间内多次访问同一页面进行反爬虫,破解起来就相对容易很多,只要请求时加入相应的 Headers 信息或者利用代理IP绕过就好。今天就到这里吧,See You!


相关图文:

  • 如何利用 C# 爬取 One 持有者返利数据!
  • 如何利用 C# 爬取Gate.io交易所的公告!
  • 如何利用 C# 爬取BigOne交易所的公告!
  • 如何利用 C# 爬取 ONE 的交易数据?
  • 如何利用 C# 实现 K 最邻近算法?
  • 如何利用 C# 实现 K-D Tree 结构?
  • 如何利用 C# + KDTree 实现 K 最邻近算法?
  • 如何利用 C# 对神经网络模型进行抽象?
  • 如何利用 C# 实现神经网络的感知器模型?
  • 如何利用 C# 实现 Delta 学习规则?
  • 如何利用 C# 爬取「京东 - 计算机与互联网图书销量榜」!
  • 如何利用 C# 爬取「当当 - 计算机与互联网图书销量榜」!
  • 如何利用 C# 爬取「互动出版网 - 计算机图书销量榜」!
  • 如何利用 C# 爬取「中国图书网 - 计算机与互联网图书销量榜」!
  • 如何利用 C# 爬取带 Token 验证的网站数据?

http://lihuaxi.xjx100.cn/news/256084.html

相关文章

开源程序员愤怒控诉!Github的「AI码农」Copilot就是寄生虫

视学算法报道 编辑&#xff1a;David【导读】以方便程序员写代码为名&#xff0c;吸血开源社区为实&#xff0c;Github的「AI码农」Copilot其实就是个寄生虫&#xff1f;Github去年推出的「AI程序员」Copilot曾一度受到程序员的热捧&#xff0c;但一个争议始终没有解决。既然是…

C# 获取图片的EXIF 信息

关于 EXIF 信息的介绍。 1 EXIF&#xff0c;是英文Exchangeable Image File(可交换图像文件)的缩写。EXIF是一种图像文件格式&#xff0c;只是文件的后缀名为jpg。EXIF信息是由数码相机在拍摄过程中采集一系列的信息&#xff0c;然后把信息放置在jpg文件的头部&#xff0c;也就…

机器学习的出现,是否意味着“古典科学”的过时?

作者&#xff1a;Laura Spinney译者&#xff1a;刘媛媛原文&#xff1a;Are we witnessing the dawn of post-theory science?让我们回忆一下&#xff0c;Isaac Newton 被一个苹果砸中头部&#xff0c;然后是怎么提出牛顿第二定律——万有引力的&#xff1f;大概过程是这样的&…

不做调参侠,重视数据及处理能力?吴恩达发起的Data-Centric赛事总结!

赛题名称&#xff1a;Data-Centric AI Competition比赛官网&#xff1a;https://https-deeplearning-ai.github.io/data-centric-comp/比赛链接&#xff1a;https://worksheets.codalab.org/worksheets/0x7a8721f11e61436e93ac8f76da83f0e6赛题介绍在大多数机器学习比赛中&…

UUID正在被NanoID取代?

欢迎关注方志朋的博客&#xff0c;回复”666“获面试宝典UUID 是软件开发中最常用的通用标识符之一。然而&#xff0c;在过去的几年里&#xff0c;其他的竞品挑战了它的存在。其中&#xff0c;NanoID 是 UUID 的主要竞争对手之一。因此&#xff0c;在本文中&#xff0c;我们将展…

ASP.NET Core 2 学习笔记(七)路由

ASP.NET Core通过路由(Routing)设定&#xff0c;将定义的URL规则找到相对应行为&#xff1b;当使用者Request的URL满足特定规则条件时&#xff0c;则自动对应到相符合的行为处理。从ASP.NET就已经存在的架构&#xff0c;而且用法也很相似&#xff0c;只有些许的不同。本篇将介绍…

Ubuntu Vim YouCompleteMe 安装

0. 必要工具安装 sudo apt-get install build-essential cmake 1. 安装 vundle mkdir ~/.vim/bundle git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle 2.编辑 .vimrc set nocompatible " be iMproved, required filetype off …

基于 OpenCV 的表格文本内容提取

作者 | 小白来源 | 小白学视觉小伙伴们可能会觉得从图像中提取文本是一件很麻烦的事情&#xff0c;尤其是需要提取大量文本时。PyTesseract是一种光学字符识别&#xff08;OCR&#xff09;&#xff0c;该库提了供文本图像。PyTesseract确实有一定的效果&#xff0c;用PyTessera…