当前位置:首页 > 综合

爬取猫眼电影网站代码

猫眼电影的猫眼数据接口没做太复杂的加密,至少比某些电商网站友好得多。电影代码直接打开浏览器开发者工具,网站切到Network面板,猫眼刷新《热辣滚烫》的电影代码详情页,就能看到一堆XHR请求。网站其中那个返回JSON的猫眼,地址里带着movieId和token参数,电影代码就是网站我们要的东西。

先别急着写代码。猫眼手动请求一次那个URL,电影代码把Headers复制出来看看。网站User-Agent、猫眼Referer、电影代码Cookie这三样基本就够了。网站Referer必须带上,否则猫眼会返回403。Cookie里有个叫_lxsdk_cuid的字段,随便填个值也能过,但最好从浏览器里原样复制。

用Python的requests库试一下:

import requests url = "https://piaofang.maoyan.com/dashboard-ajax/movie" params = {  "movieId": 1355909, "orderType": 0, "uuid": "你的uuid", "timeStamp": 1700000000, "index": 0, "channelId": 40009, "sVersion": 2, "signKey": "你的signKey" } headers = {  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Referer": "https://piaofang.maoyan.com/dashboard" } resp = requests.get(url, params=params, headers=headers) print(resp.json()) 

这里有个坑。猫眼对时间戳和signKey做了校验。signKey是前端JS算出来的,直接硬编码一个固定值,过几分钟就会失效。我试过用Selenium自动打开页面,等JS执行完再提取signKey,但这样速度太慢。后来发现一个取巧的办法:用猫眼自己的接口返回的signKey,循环调用时每次从响应头里拿新的。不过这个接口本身有频率限制,大概每分钟20次左右,超了会返回429。

另一个思路是直接抓猫眼专业版的票房数据。那个页面是服务端渲染的,用BeautifulSoup解析HTML就行,不用处理JS加密。缺点是数据更新有延迟,大概每小时才刷新一次。如果你只是做趋势分析,这个延迟可以接受。

from bs4 import BeautifulSoup html = requests.get("https://piaofang.maoyan.com/dashboard", headers=headers).text soup = BeautifulSoup(html, "html.parser") rows = soup.select(".movie-list .row") for row in rows: name = row.select_one(".movie-name").text.strip() box = row.select_one(".box-office").text.strip() print(name, box) 

实际跑的时候,我发现猫眼会检测请求频率。连续请求50次以上,IP会被临时封禁。解决办法是用代理池,或者把请求间隔调到3秒以上。我试过用ProxyBroker自动抓免费代理,但免费代理的可用率不到10%,而且很多已经被猫眼拉黑了。最后花了点钱买了动态代理,问题才解决。

数据拿到手之后,清洗是个麻烦事。猫眼返回的JSON里,票房数字是字符串,带“万”和“亿”单位。得写个函数转换:

def parse_box_office(text): if "亿" in text: return float(text.replace("亿", "")) * 100000000 elif "万" in text: return float(text.replace("万", "")) * 10000 return float(text) 

还有上映天数、排片占比这些字段,有时候是空的。空值直接跳过,别用0填充,否则算平均值得出错误结论。

最后说个观察。猫眼在2023年之后改了接口,把部分数据放到了WebSocket里推送。用requests抓不到实时票房,只能拿到快照。如果你需要秒级更新,得用websocket-client库连上wss://piaofang.maoyan.com/ws,然后解析二进制消息。这个我没深入做,因为对大多数分析场景来说,分钟级延迟已经够了。

代码写完记得加异常处理。猫眼的接口偶尔会返回HTML错误页,json.loads直接抛异常。用try-except包住,失败就重试,重试三次还不行就跳过。别让一个请求失败把整个爬虫搞崩。

分享到: