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

时间:2019-07-09 10:30:01 来源:浙江it网 当前位置:小布丁线报 > 课件 > 手机阅读

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

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

字体编码

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

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

字体编码

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

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

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

stonefont类

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

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

打包main.py文件的代码:

pyinstaller -F main.py

生成的 XML 文件如下:

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

图形信息

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

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

映射关系

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


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

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

public class FontGlyph
{
///
/// 图形名称
///

public string Name { get; set; }
///
/// 图形数据
///

public string Glyph { get; set; }
///
/// 图形值
///

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

private static List GetXmlGlyf(string path)
{
List result = new List();
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 GetFontGlyphList(string fileName)
{
List 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 lstModel, List 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 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 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 GetFilmsTicket()
{
List result = new List();
string url = "https://maoyan.com/board/1"; //国内票房榜
IHtmlDocument doc = GetHtmlDocument(url);
if (doc == null)
return result;
List lstModel = GetFontGlyphList(@".\font\base.xml");
List woffStr = doc.Find("style").ToList();
string tempUrl = GetWoffUrl(woffStr[0].InnerHtml());
string fileNameWoff = Download(tempUrl);
string fileNameXml = TransXml(fileNameWoff);
List lstNew = GetXmlGlyf(fileNameXml);
List lists = doc.Find("dd").ToList();
for (int i = 0; i < lists.Count; i++)
{
List infor = lists[i].Find("p").ToList();
Film item = new Film();
item.Num = i + 1; //排名
string dw, ticket;
List 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]; //获取影片url
item.MovieName = a.InnerHtml().Trim(); //名称
url = "https://maoyan.com" + a.Attribute("href").AttributeValue;
IHtmlDocument temp = GetHtmlDocument(url);
List t = temp.Find("li.ellipsis").ToList();
item.Type = t[0].InnerHtml(); //类型
List b = temp.Find(".dra").ToList();
item.Introduction = b[0].InnerHtml(); //介绍
result.Add(item);
}
return result;
}

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

public static List GetFilmsExpect(int offset)
{
List result = new List();
string url = "https://maoyan.com/board/6"; //最受期待榜
IHtmlDocument doc = GetHtmlDocument(url, offset);
if (doc == null)
return result;
List lstModel = GetFontGlyphList(@".\font\base.xml");
List woffStr = doc.Find("style").ToList();
string tempUrl = GetWoffUrl(woffStr[0].InnerHtml());
string fileNameWoff = Download(tempUrl);
string fileNameXml = TransXml(fileNameWoff);
List lstNew = GetXmlGlyf(fileNameXml);
List lists = doc.Find("dd").ToList();
for (int i = 0; i < lists.Count; i++)
{
List 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 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]; //获取影片url
item.MovieName = a.InnerHtml().Trim(); //名称
url = "https://maoyan.com" + a.Attribute("href").AttributeValue;
IHtmlDocument temp = GetHtmlDocument(url);
List t = temp.Find("li.ellipsis").ToList();
item.Type = t[0].InnerHtml(); //类型
List b = temp.Find(".dra").ToList();
item.Introduction = b[0].InnerHtml(); //介绍
result.Add(item);
}
return result;
}

10. 输出结果

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

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

结果1

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

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

结果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 验证的网站数据?

上一篇别以为“乖”宝宝很省心!太乖的宝宝,家长可要警惕这6种病!

下一篇火到全网资源下架,这部泰剧才是2019第一爆!

课件本月排行

课件精选