前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python爬虫教程,爬取猫眼电影 ,一网打尽好电影

python爬虫教程,爬取猫眼电影 ,一网打尽好电影

作者头像
python学习教程
发布2019-07-10 10:25:44
6720
发布2019-07-10 10:25:44
举报

前言

Python现在非常火,语法简单而且功能强大,很多同学都想学Python!所以小的给各位看官们准备了高价值Python学习视频教程及相关电子版书籍,欢迎前来领取!

一、页面分析

首先打开猫眼电影,然后点击一个正在热播的电影(比如:毒液)。打开开发者工具,点击左上角的箭头,然后用鼠标点击网页上的票价,可以看到源码中显示的不是数字,而是某些根本看不懂的字符,这是因为使用了font-face定义字符集,并通过unicode去映射展示,所以我们在网页上看到的是数字,但是在源码中看到的却是别的字符。

碰到这些根本看不懂的字符怎么办呢?不慌,右键选择查看网页源代码,然后找到相应的位置(如下图)。那么是不是“”映射出来就是28呢?

通过查看源码,可以找到如下内容, 而当我们访问这里面的链接的时候,就可以下载相应的字体文件,关于font-face可以点击这里查看了解:

当我下载好字体文件后,满心欢喜的双击想要点开的时候,却发现无法打开(T_T)。查阅资料之后知道了一个叫做FontCreator的软件,用这个软件可以打开我们下载的字体文件,没有安装这个软件的可以进入官网https://www.high-logic.com/下载安装

,如果下载得很慢的可以用百度云下载(链接:https://pan.baidu.com/s/1ImxwPhKdzZo2g4bIjiGCZw ,提取码:m0yf )。下载好之后打开软件,看到如下界面,选择Use Evaluation Version,这个软件我们可以免费使用三十天。

打开软件后,再打开我们下载的字体文件,可以看到数字2和8分别对应的是uniE83B和uniE375,和前面看到的编码是一致的。

那么我们下载好字符集之后,只要将其中的字符编码和数字对应的信息提取出来,再把网页源码中的字符编码替换掉,就能得到我们想要的数据了。这里要用到一个三方库fontTools,利用fontTools可以获取每一个字符对象,这个对象你可以简单的理解为保存着这个字符的形状信息,而且编码可以作为这个对象的id,具有一一对应的关系。不过这里还有一个问题,就是网页每次使用的字符集是随机变化的,我们也就无法使用一个固定的字符集去做到反爬。

解决思路如下:先保存一个字体文件(比如base.woff),然后解析其数字和编码的对应关系,然后爬取的时候把新的字体文件下载下来(比如online.woff),网页中的一个数字的编码(比如ABCD),我们先通过编码ABCD找到这个字符在online.woff中的对象,并且把它和base.woff中的对象逐个对比,直到找到相同的对象,然后获取这个对象在base.woff中的编码,再通过编码确认是哪个数字。

二、主要代码

解析下载的字体文件,由于字体文件中有多余的字符,需要舍弃掉。

# 解析字体库
def parse_ttf(font_name):
    """
    :param font_name: 字体文件名
    :return: 字符-数字字典
    """
    base_nums = ['3', '0', '1', '6', '4', '2', '5', '8', '9', '7']
    base_fonts = ['uniEB84', 'uniF8CA', 'uniEB66', 'uniE9DB', 'uniE03C',
                  'uniF778', 'uniE590', 'uniED12', 'uniEA5E', 'uniE172']
    font1 = TTFont('base.woff')  # 本地保存的字体文件
    font2 = TTFont(font_name)  # 网上下载的字体文件
 
    uni_list = font2.getGlyphNames()[1:-1]  # 去掉头尾的多余字符
    temp = {}
    # 解析字体库
    for i in range(10):
        uni2 = font2['glyf'][uni_list[i]]
        for j in range(10):
            uni1 = font1['glyf'][base_fonts[j]]
            if uni2 == uni1:
                temp["&#x" + uni_list[i][3:].lower() + ";"] = base_nums[j]
    return temp

解析网页源码,把其中的编码替换成数字,这里选择把网页源码保存下来,这样的话编码就不会改变,也就能正确的解析。

# 解析网页得到数字信息
def get_nums(font_dict):
    """
    :param font_dict: 字符-数字字典
    :return: 由评分、评分人数、票房和票价组成的列表
    """
    num_list = []
    with open('html', 'r', encoding='utf-8') as f:
        for line in f.readlines():
            lst = re.findall('(&#x.*?)<', line)
            if lst:
                num = lst[0]
                for i in font_dict.keys():
                    if i in num:
                        num = num.replace(i, font_dict[i])
                num_list.append(num)
    return num_list

完整代码

import re
import requests
from lxml import etree
from fontTools.ttLib import TTFont
headers = {
    "Host": "maoyan.com",
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 "
                  "Safari/537.36"
}
 
 
# 解析字体库
def parse_ttf(font_name):
    """
    :param font_name: 字体文件名
    :return: 字符-数字字典
    """
    base_nums = ['3', '0', '1', '6', '4', '2', '5', '8', '9', '7']
    base_fonts = ['uniEB84', 'uniF8CA', 'uniEB66', 'uniE9DB', 'uniE03C',
                  'uniF778', 'uniE590', 'uniED12', 'uniEA5E', 'uniE172']
    font1 = TTFont('base.woff')  # 本地保存的字体文件
    font2 = TTFont(font_name)  # 网上下载的字体文件
 
    uni_list = font2.getGlyphNames()[1:-1]  # 去掉头尾的多余字符
    temp = {}
    # 解析字体库
    for i in range(10):
        uni2 = font2['glyf'][uni_list[i]]
        for j in range(10):
            uni1 = font1['glyf'][base_fonts[j]]
            if uni2 == uni1:
                temp["&#x" + uni_list[i][3:].lower() + ";"] = base_nums[j]
    return temp
 
 
# 解析网页得到数字信息
def get_nums(font_dict):
    """
    :param font_dict: 字符-数字字典
    :return: 由评分、评分人数、票房和票价组成的列表
    """
    num_list = []
    with open('html', 'r', encoding='utf-8') as f:
        for line in f.readlines():
            lst = re.findall('(&#x.*?)<', line)
            if lst:
                num = lst[0]
                for i in font_dict.keys():
                    if i in num:
                        num = num.replace(i, font_dict[i])
                num_list.append(num)
    return num_list
 
 
# 爬取页面
def get_page():
    url = "http://maoyan.com/cinemas?movieId=42964"
    res = requests.get(url, headers=headers)
    # 提取woff字体的链接
    woff_url = re.findall(r"vfile.*?woff", res.text)[0]
    # 下载字体文件
    font_name = 'online.woff'
    with open(font_name, 'wb') as f:
        f.write(requests.get("http://" + woff_url).content)
    # 保存res.text用于后面解析
    with open('html', 'w', encoding='utf-8') as f:
        f.write(res.text)
    # 解析字体文件
    font_dict = parse_ttf(font_name)
    nums = get_nums(font_dict)
    price_list = nums[3:]  # 得到票价信息列表
    s = etree.HTML(res.text)
    movie_name = s.xpath('/html/body/div[3]/div/div[2]/div[1]/h3/text()')[0]  # 名字
    movie_type = s.xpath('/html/body/div[3]/div/div[2]/div[1]/ul/li[1]/text()')[0]  # 类型
    info = s.xpath('/html/body/div[3]/div/div[2]/div[1]/ul/li[2]/text()')[0]
    movie_country = info.strip().split('\n')[0]  # 国家
    movie_time = info.strip().split('\n')[1].split('/ ')[-1]  # 时长
    movie_score = nums[0] + '(评分人数:{})'.format(nums[1])  # 评分
    box_office = nums[2] + s.xpath('/html/body/div[3]/div/div[2]/div[3]/div[2]/div/span[2]/text()')[0]  # 票房
    cinema_list = s.xpath('//*[@id="app"]/div[2]/div/div[1]/a/text()')
    address_list = s.xpath('//*[@id="app"]/div[2]/div/div[1]/p/text()')
    print(movie_name)
    print(movie_type + "/" + movie_country + "/" + movie_time)
    print("评分:"+movie_score, "票房:"+box_office)
    for cinema, address, price in zip(cinema_list, address_list, price_list):
        print(cinema, address, "票价:" + price + "元")
 
 
if __name__ == '__main__':
    get_page()

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 python教程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 完整代码
相关产品与服务
云开发 CLI 工具
云开发 CLI 工具(Cloudbase CLI Devtools,CCLID)是云开发官方指定的 CLI 工具,可以帮助开发者快速构建 Serverless 应用。CLI 工具提供能力包括文件储存的管理、云函数的部署、模板项目的创建、HTTP Service、静态网站托管等,您可以专注于编码,无需在平台中切换各类配置。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档