python采集電影數(shù)據(jù)JS逆向, 并制作可視化

嗨嘍~大家好呀,這里是魔王吶 ? ~!

環(huán)境使用:

  • Python 3.10

  • Pycharm

  • nodejs

模塊使用:

  • requests -> pip install requests

  • execjs -> pip install pyexecjs

  • json

  • csv

模塊安裝:

win + R 輸入cmd 輸入安裝命令 pip install 模塊名 (如果你覺得安裝速度比較慢, 你可以切換國內(nèi)鏡像源)

實(shí)現(xiàn)爬蟲流程:

一. 數(shù)據(jù)來源分析

1. 明確需求: 明確采集的網(wǎng)址以及數(shù)據(jù)內(nèi)容
    - 網(wǎng)址: https://www.endata.com.cn/BoxOffice/BO/Year/index.html
    - 數(shù)據(jù): 電影數(shù)據(jù)
2. 抓包分析: 通過開發(fā)者工具(瀏覽器自帶)進(jìn)行分析
    - 打開開發(fā)者工具: F12 / 右鍵點(diǎn)擊檢查選擇network (網(wǎng)絡(luò))
    - 選擇任意年份: 讓它加載對應(yīng)的數(shù)據(jù)內(nèi)容
    查看返回的數(shù)據(jù)內(nèi)容:
        請求網(wǎng)址: https://www.endata.com.cn/API/GetData.ashx
        請求方式: POST (需要向服務(wù)器提交表單數(shù)據(jù))
        請求頭: (是否有加密參數(shù))
        請求參數(shù):
            year: 2023
            MethodName: BoxOffice_GetYearInfoData
        響應(yīng)數(shù)據(jù):
            密文內(nèi)容 (加密內(nèi)容)
    - 對于加密的數(shù)據(jù), 進(jìn)行解密
        分析加密規(guī)則, 如何解密 (查看啟動(dòng)器)
    斷點(diǎn)目的: 刷新網(wǎng)頁 / 翻頁時(shí)候, 網(wǎng)頁運(yùn)行到這個(gè)地方可以暫停住
        傳入了什么參數(shù), 返回了什么內(nèi)容

二. 代碼實(shí)現(xiàn)步驟

1. 發(fā)送請求 -> 模擬瀏覽器對于url地址發(fā)送請求
2. 獲取數(shù)據(jù) -> 獲取服務(wù)器返回響應(yīng)數(shù)據(jù)
    獲取密文數(shù)據(jù) -> 解密
3. 解析數(shù)據(jù) -> 提取我們數(shù)據(jù)內(nèi)容
4. 保存數(shù)據(jù) -> 保存數(shù)據(jù)

數(shù)據(jù)采集

# 導(dǎo)入數(shù)據(jù)請求模塊: 需要安裝 pip install requests
import requests
# 需要安裝 pip install pyexecjs
import execjs
# 導(dǎo)入json模塊
import json
# 導(dǎo)入csv模塊
import csv

"""保存數(shù)據(jù)"""

# 創(chuàng)建文件對象
csv_file = open('data.csv', mode='w', encoding='utf-8', newline='')
csv_writer = csv.DictWriter(csv_file, fieldnames=[
    '影片名稱',
    '類型',
    '總票房',
    '平均票價(jià)',
    '場均人次',
    '國家地區(qū)',
    '上映時(shí)間',
])
csv_writer.writeheader()

"""1. 發(fā)送請求 -> 模擬瀏覽器對于url地址發(fā)送請求"""

# 模擬瀏覽器
headers = {
    # User-Agent 用戶代理 表示瀏覽器基本身份信息
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}
for year in range(2008, 2024):
    # 請求網(wǎng)址
    url = 'https://www.endata.com.cn/API/GetData.ashx'
    # 請求參數(shù)
    data = {
        'year': year,
        'MethodName': 'BoxOffice_GetYearInfoData'
    }
    # 發(fā)送請求
    response = requests.post(url=url, data=data, headers=headers)

"""2. 獲取數(shù)據(jù) -> 獲取服務(wù)器返回響應(yīng)數(shù)據(jù)"""

    content = response.text
    print('密文數(shù)據(jù): ', content)  # 查看是否得到數(shù)據(jù)內(nèi)容
    """解密數(shù)據(jù)
    - 通過JS代碼變成明文數(shù)據(jù) (分析解密數(shù)據(jù)代碼位置)
    - 通過python代碼調(diào)用js代碼
    """
    # 讀取js代碼
    f = open('demo.js', encoding='utf-8').read()
    # 編譯js代碼
    js_code = execjs.compile(f)
    # 調(diào)用js代碼函數(shù)
    res = js_code.call('get_content', content)
    # 轉(zhuǎn)成字典數(shù)據(jù)
    json_data = json.loads(res)
    print('明文數(shù)據(jù): ', res)
    print(json_data)

"""3. 解析數(shù)據(jù) -> 提取我們數(shù)據(jù)內(nèi)容"""

    Table = json_data['Data']['Table']
    # for 循環(huán)遍歷, 提取列表元素
    for index in Table:
        # 把數(shù)據(jù)保存到字典里面
        dit = {
            '影片名稱': index['MovieName'],
            '類型': index['Genre_Main'],
            '總票房': index['BoxOffice'],
            '平均票價(jià)': index['AvgPrice'],
            '場均人次': index['AvgPeoPle'],
            '國家地區(qū)': index['Area'],
            '上映時(shí)間': index['ReleaseTime'],
        }
        # 寫入數(shù)據(jù)
        csv_writer.writerow(dit)
        print(dit)

數(shù)據(jù)可視化

# 需要安裝 pip install pandas
import pandas as pd
from pyecharts.globals import CurrentConfig, NotebookType
CurrentConfig.NOTEBOOK_TYPE = NotebookType.JUPYTER_LAB
# 讀取文件
df = pd.read_csv('data.csv')
# 顯示前5行數(shù)據(jù)
df.head()

可以直接通過pyechrats 官文文檔 實(shí)現(xiàn)可視化分析

https://gallery.pyecharts.org/#/README
info = df['類型'].value_counts().index.to_list() # x軸的數(shù)據(jù)
num = df['類型'].value_counts().to_list() # y軸的數(shù)據(jù)
from pyecharts import options as opts
from pyecharts.charts import Pie
from pyecharts.faker import Faker

c = (
    Pie()
    .add(
        "",
        [
            list(z)
            for z in zip(
                info,
                num,
            )
        ],
        center=["40%", "50%"],
    )
    .set_global_opts(
        # 設(shè)置標(biāo)題
        title_opts=opts.TitleOpts(title="2008-2023年部分電影類型分布"),
        legend_opts=opts.LegendOpts(type_="scroll", pos_left="80%", orient="vertical"),
    )
    .set_series_opts(label_opts=opts.LabelOpts(formatter=": {c}"))
    # 把可視化圖保存成html文件
    # .render("2008-2023年部分電影類型分布(餅圖).html")
)
c.load_javascript()
c.render_notebook()
from pyecharts import options as opts
from pyecharts.charts import Pie
from pyecharts.faker import Faker
info = df['國家地區(qū)'].value_counts().index.to_list() # x軸的數(shù)據(jù)
num = df['國家地區(qū)'].value_counts().to_list() # y軸的數(shù)據(jù)
c = (
    Pie()
    .add(
        "",
        [
            list(z)
            for z in zip(
                info,
                num,
            )
        ],
        center=["40%", "50%"],
    )
    .set_global_opts(
        # 設(shè)置標(biāo)題
        title_opts=opts.TitleOpts(title="2008-2023年部分電影國家地區(qū)分布"),
        legend_opts=opts.LegendOpts(type_="scroll", pos_left="80%", orient="vertical"),
    )
    .set_series_opts(label_opts=opts.LabelOpts(formatter=": {c}"))
    # 把可視化圖保存成html文件
    # .render("2008-2023年部分電影類型分布(餅圖).html")
)
c.render_notebook()
df.head()
Top = df[['影片名稱', '總票房']].sort_values('總票房')[-10:]
name = list(Top['影片名稱'])
num = list(Top['總票房'])

from pyecharts import options as opts
from pyecharts.charts import Bar

c = (
    Bar()
    .add_xaxis(name)
    .add_yaxis("", num)
    .set_global_opts(
        xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),
        title_opts=opts.TitleOpts(title="2008-2023年部分電影總票房Top10分布", subtitle=""),
    )
    # .render("bar_rotate_xaxis_label.html")
)
c.render_notebook()

尾語

最后感謝你觀看我的文章吶~本次航班到這里就結(jié)束啦 ??

希望本篇文章有對你帶來幫助 ??,有學(xué)習(xí)到一點(diǎn)知識~

躲起來的星星??也在努力發(fā)光,你也要努力加油(讓我們一起努力叭)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容