需要采集的数据:
现在暂时没有数据了。。
pc端显示的价格比手机端的要贵些,因为手机端的才能看到活动折扣后的价格,但是我们获取到初始定价,知道活动规则就可以得到最终价格了。
过程
1、需要采集的数据无需登陆:cookie应该不需要设置
2、我们要批量获取几家影城的,所以先到上级页面来获取下影城的链接。
3、网站返回的数据,header的[‘Accept’]首选是‘text/html’…(即所得即所看的文本形式的网页)。接受编码居然选择了gzip,但是所幸返回的数据没有经过gzip压缩,直接是我们可视的文本。
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive',
'Cookie': '__mta=107249341.1561347981570.1561347988040.1561348184374.3; uuid_n_v=v1; uuid=A19C3150963211E9B29A7B3758C1D4B1D5583BD641614CE2B98C66413750ECB6; _csrf=08b77a55c8e425a9d26f3828263e8c09d54b7640c657d5dc29d803d267dacaaf; _lxsdk_cuid=16b87978007bc-0e52b641c038ea-3f385804-15f900-16b87978008c8; _lxsdk=A19C3150963211E9B29A7B3758C1D4B1D5583BD641614CE2B98C66413750ECB6; __mta=107249341.1561347981570.1561347981570.1561347981570.1; _lxsdk_s=16b882e5c34-786-46a-f7a%7C%7C1',
'Host': 'maoyan.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
能看到我们要获取的 影院名字 和 链接 在这里:
来一手正则提取出来
r'cinema-info">.*?<a href="(.*?)".*?>(.*?)</a>'
3、获取影院的连接后,进去看数据返回页。
发现网页使用到: 网页开放字体格式(WOFF)其实他返回的也是也是html文本。但是每次刷新都会返回不同的stone字体。每次刷新页面,返回的场次数据中的数字都是 &#x + 4位随机变换的小写英文数字组合 + “:",如: 对比网页中的数字,可以发现表示的是0-9中的任何一个数字。
下面我们请求woff的链接,前面加上“https:",但是我们读取woff一般需要专门的软件,我直接读取是乱码的。
但是我们可以用TTFont的轮子将woff文件存为xml文件。
TTFont("maoyan.woff").saveXML("maoyan.xml")
这下能看到字体内容了!
网页中这种形式的字符,原型是unie964;,是一种自定义编码的字体。
刚刚我们看到网站使用 自定义字体 来表示 0-9
我们需要找到字体文件并判断字体里面每个字符是一个什么数字,然后还原对应uni编码的数字。(再次正则把字体链接找出来。)
上图中是字体xml文件的第一部分,这像是一个目录,共有0-11个id,对应12个字。
然后是字体的头部信息,记录了字体创建时间,一些字体相关设置、版本。
最上面有句注释:
<!-- Most of this table will be recalculated by the compiler -->
意思是:这个表的大部分将由编译器重新计算
接下来的节点还是字体相关信息,但我还是不知道他每个是什么数字。
图一 | 图二 | 设置 |
1、图一是最值点信息,例如maxPoints最多的点数是58个点…… 2、图二是的节点标题是os,看配置信息是关于脚本、类型、风格、范围、序号的一些设置。 3、看到这里我仍然是啥头绪的,接着看下面几个。 | ||
1、图一记录了字体中每个字的宽度。 2、图二是0x和uni对的对应关系,0xe7ca是c/c++中的16进制数的表示,这里形成一个16进制数跟字体编码的对应关系 | ||
1、接下来这个找到这个TTGlyh,可以看到字编码都在里面了,点开还能看到一个个的x,y坐标点。 2、我一开始也没头绪,后面发现TTFont可以把这些坐标都读取出来,然后我用matopollic给他画一下这个是什么数字。 3、接着就是想了点算法根据数字他的坐标点范围来判断这是个什么数字,从而还原了正确的字符。 | ||
1、图一这个是names,跟每个字的id有关,没太搞得懂了 2、图二是一个post: 第一段注释说:这个文件使用唯一的符号名基于“post”表中找到的信息。因为这些名字可能不是唯一的,为了避免冲突,我们不得不编造一些假名。为了为了能够保留原来的信息,我们需要一个名字来不同情况下的ps名称映射。这就是你下面看到的。 3、第二段注释说:下面是取自非标准Mac符号顺序的名称 4、总结一下:这个应该说了这个名字的创建由来,详细的不懂。 | ||
1、最后一个GSUB,说实话没看懂,看似有这些lookupList查找列表、但是不知怎么使,具体要查查资料。 2、下面说说我对Glyph(每个符号)的坐标分析以判断是啥数字的方法。 |
直接上核心代码:
1、TTFont读取woff
爬取中可以不保存xml,TTFont可以直接读取woff。
第一步:读取‘cmap’使用getGlyphOrder()方法,获取每个编码(如uniED83)。
第二步:获取glyph节点中<contour>节点的数量,1个节点代表1条由多个坐标连成的线(就像我现在展开的uniF226下面有3个<contour>节点,那么就说明他有3条线了,我们很容易就能想到也就是空心的数字8需要画3条线,也就是3笔。
第三步:把<contour>下面具体的坐标值获取出来。
第四步:根据这个Glyph(符号)的轮廓数、坐标点写判断逻辑、以得到真实的数字,将得到的编码名字和对应数字放入字典,遍历返回文本将编码还原为数字。
for k, v in p.items():
otext.replace(k.lower() + ';', str(v))
得到正确的数据后,就可以开始提取了。我那时用的是xpath提取。
确实有点太冗长了,现在的话我应该会用正则直接拿出来了。我把数据弄到pd里了,最后用了openpyxl引擎,来获取一些最大行数,每次导出数据都会先清除原来的,并不会破坏excel中的格式,如果直接df.to_excel就会把excel一些条件格式的东西也请了,所以这里用了一下。