资讯专栏INFORMATION COLUMN

requests+正则表达式+multiprocessing多线程抓取猫眼电影TOP100

jifei / 2650人阅读

摘要:本文介绍利用库库和正则表达式爬取猫眼电影电影的相关信息,提取出电影名称上映时间评分封面图片等信息,将爬取的内容写入到文件中。获取到不同的网页后使用正则表达式提取出我们要的信息,就可以得到电影信息了,可以使用多线程加速爬取。

本文介绍利用Requests库、multiprocessing库和正则表达式爬取猫眼电影TOP100电影的相关信息,提取出电影名称、上映时间、评分、封面图片等信息,将爬取的内容写入到文件中。站点URL为 http://maoyan.com/board/4

准备

本文使用了Requests库,使用pip安装: pip install requests

分析

打开http://maoyan.com/board/4,可以看到榜单信息。如下图所示

排名第一的电影是霸王别姬,可以提取的信息有电影名称、主演、上映时间、评分、封面图等。
点击页面下方的分页列表翻页到第二页,会发现URL会变成https://maoyan.com/board/4?offset=10,比首页多了个offset=10 参数,而目前显示的是排名11-20的电影,初步判断这是偏移量参数。再点击下一页,URL变成了https://maoyan.com/board/4?offset=20offset变成了20,显示的是排名21-30的电影。
由此可见,offset代表偏移量,偏移量为n,则显示的是排名n+1~n+10的电影,每页显示10个电影。所以,想要获取TOP100电影信息,只要分开获取10次,只需把10次请求的URL中offset参数分别设为 0,10,20,30...90即可(首页的offset值为0)。获取到不同的网页后使用正则表达式提取出我们要的信息,就可以得到TOP100电影信息了,可以使用多线程加速爬取。

爬取实现 爬取首页

实现get_page()方法,传入url参数可以将抓取的页面结果返回。以下代码获取首页内容:

import requests
from requests.exceptions import RequestException

def get_page(url):
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"
    }
    response = requests.get(url,headers = headers)
    try:
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        print("request error")
        return None

def main():
    html = get_page("https://maoyan.com/board/4")
    print(html)

main()

运行之后就成功获取到了首页的源代码,接下来使用正则表达式进行解析,提取出我们想要的信息。

正则提取

回到浏览器页面,在开发者工具Network监听组件中查看源代码。如图:

值得注意的是这里不是从Elements选项卡里查看的源代码,因为Elements里看到的源代码很有可能经过Javascript处理过从而和原始请求不同,所以要从Network选项卡里查看原始请求得到的源码。

查看此处代码:


不难发现,要爬取的每部电影信息都在

标签里,接下来使用正则表达式提取信息。

首先,提取它的排名信息,它的排名信息在classboard-indexi标签里,使用非贪婪匹配来提取i内的信息,正则表达式可以写为:

.*?board-index.*?>(d+)

接下来提取电影的封面图片。在排名后面的a便签里有两个img便签,经过检查,第二个img是电影的封面图片,正则:.*?data-src="(.*?)"

然后提取电影的名称,它在classname

便签内,可以使用name作为标志位进一步提取到其内a的文本内容,正则写为:.*?name.*?a.*?>(.*?)

提取主演:.*?star">(.*?)


提取上映时间:.*?releasetime">(.*?)


提取评分:.*?integer">(.*?).*?fraction">(.*?).*?

最后正则表达式写为:

.*?board-index.*?>(d+).*?data-src="(.*?)".*?name.*?a.*?>(.*?).*?star">(.*?)

.*?releasetime">(.*?)

.*?integer">(.*?).*?fraction">(.*?).*?

上面的正则表达式可以匹配一个电影,匹配了7条信息,接下来可以通过findall()方法提取所有内容。可以定义一个用来解析页面的方法parse_page(),代码如下:

def parse_page(html):
    pattern = re.compile("
.*?board-index.*?>(d+).*?data-src="(.*?)".*?name.*?a.*?>(.*?).*?star">(.*?)

" + ".*?releasetime">(.*?)

.*?integer">(.*?).*?fraction">(.*?).*?
",r.S) #re.S使.能匹配任意字符 items = pattern.findall(str(html))

这样就成功得拿到了一页10个电影的信息,这是一个列表,获取到的结果如下:

[("1", "https://p1.meituan.net/movie/20803f59291c47e1e116c11963ce019e68711.jpg@160w_220h_1e_1c", "霸王别姬", "
                主演:张国荣,张丰毅,巩俐
        ", "上映时间:1993-01-01", "9.", "6"), ("2", "https://p0.meituan.net/movie/283292171619cdfd5b240c8fd093f1eb255670.jpg@160w_220h_1e_1c", "肖申克的救赎", "
                主演:蒂姆·罗宾斯,摩
根·弗里曼,鲍勃·冈顿
        ", "上映时间:1994-10-14(美国)", "9.", "5"), ("3", "https://p0.meituan.net/movie/54617769d96807e4d81804284ffe2a27239007.jpg@160w_220h_1e_1c", "罗
马假日", "
                主演:格利高里·派克,奥黛丽·赫本,埃迪·艾伯特
        ", "上映时间:1953-09-02(美国)", "9.", "1"), ("4", "https://p0.meituan.net/movie/e55ec5d18ccc
83ba7db68caae54f165f95924.jpg@160w_220h_1e_1c", "这个杀手不太冷", "
                主演:让·雷诺,加里·奥德曼,娜塔莉·波特曼
        ", "上映时间:1994-09-14(法国)", "9.", "
5"), ("5", "https://p1.meituan.net/movie/f5a924f362f050881f2b8f82e852747c118515.jpg@160w_220h_1e_1c", "教父", "
                主演:马龙·白兰度,阿尔·帕西诺,詹姆斯·肯恩

      ", "上映时间:1972-03-24(美国)", "9.", "3"), ("6", "https://p1.meituan.net/movie/0699ac97c82cf01638aa5023562d6134351277.jpg@160w_220h_1e_1c", "泰坦尼克号", "

    主演:莱昂纳多·迪卡普里奥,凯特·温丝莱特,比利·赞恩
        ", "上映时间:1998-04-03", "9.", "5"), ("7", "https://p0.meituan.net/movie/da64660f82b98cdc1b8a3804e69609e04110
8.jpg@160w_220h_1e_1c", "唐伯虎点秋香", "
                主演:周星驰,巩俐,郑佩佩
        ", "上映时间:1993-07-01(中国香港)", "9.", "2"), ("8", "https://p0.meituan.net/movie/b076ce63e9860ecf1ee9839badee5228329384.jpg@160w_220h_1e_1c", "千与千寻", "
                主演:柊瑠美,入野自由,夏木真理
        ", "上映时间:2001-07-20(日本)", "9.", "3"), ("9", "https://p0.meituan.net/movie/46c29a8b8d8424bdda7715e6fd779c66235684.jpg@160w_220h_1e_1c", "魂断蓝桥", "
                主演:费雯·丽,罗伯特·泰勒,露塞尔·沃特森

    ", "上映时间:1940-05-17(美国)", "9.", "2"), ("10", "https://p0.meituan.net/movie/230e71d398e0c54730d58dc4bb6e4cca51662.jpg@160w_220h_1e_1c", "乱世佳人", "

主演:费雯·丽,克拉克·盖博,奥利维娅·德哈维兰
        ", "上映时间:1939-12-15(美国)", "9.", "1")]

这样的数据看上去很杂乱,使用字典将数据格式化:

for item in items:
    yield {
        "top":item[0],
        "image_src":item[1],
        "name":item[2],
        "actor":item[3].strip()[3:] if len(item[3]) > 3 else "",
        "releasetime":item[4].strip()[5:],
        "score":item[5] + item[6]
    }

这样就可以获得电影信息的结构化数据了,每个电影的信息都包含在一个字典里。获得的结果如下:

{"top": "1", "image_src": "https://p1.meituan.net/movie/20803f59291c47e1e116c11963ce019e68711.jpg@160w_220h_1e_1c", "name": "霸王别姬", "actor": "张国荣,张丰毅,巩俐", "releasetime": "1993-01-01", "score": "9.6"}
{"top": "2", "image_src": "https://p0.meituan.net/movie/283292171619cdfd5b240c8fd093f1eb255670.jpg@160w_220h_1e_1c", "name": "肖申克的救赎", "actor": "蒂姆·罗宾斯,摩根·弗里曼,鲍勃·冈顿", "releasetime": "1994-10-14(美国)", "score": "9.5"}
{"top": "3", "image_src": "https://p0.meituan.net/movie/54617769d96807e4d81804284ffe2a27239007.jpg@160w_220h_1e_1c","name": "罗马假日", "actor": "格利高里·派克,奥黛丽·赫本,埃迪·艾伯特", "releasetime": "1953-09-02(美国)", "score": "9.1"}
{"top": "4", "image_src": "https://p0.meituan.net/movie/e55ec5d18ccc83ba7db68caae54f165f95924.jpg@160w_220h_1e_1c", "name": "这个杀手不太冷", "actor": "让·雷诺,加里·奥德曼,娜塔莉·波特曼", "releasetime": "1994-09-14(法国)", "score": "9.5"}
{"top": "5", "image_src": "https://p1.meituan.net/movie/f5a924f362f050881f2b8f82e852747c118515.jpg@160w_220h_1e_1c", "name": "教父", "actor": "马龙·白兰度,阿尔·帕西诺,詹姆斯·肯恩", "releasetime": "1972-03-24(美国)", "score": "9.3"}
{"top": "6", "image_src": "https://p1.meituan.net/movie/0699ac97c82cf01638aa5023562d6134351277.jpg@160w_220h_1e_1c", "name": "泰坦尼克号", "actor": "莱昂纳多·迪卡普里奥,凯特·温丝莱特,比利·赞恩", "releasetime": "1998-04-03", "score": "9.5"}
{"top": "7", "image_src": "https://p0.meituan.net/movie/da64660f82b98cdc1b8a3804e69609e041108.jpg@160w_220h_1e_1c", "name": "唐伯虎点秋香", "actor": "周星驰,巩俐,郑佩佩", "releasetime": "1993-07-01(中国香港)", "score": "9.2"}
{"top": "8", "image_src": "https://p0.meituan.net/movie/b076ce63e9860ecf1ee9839badee5228329384.jpg@160w_220h_1e_1c", "name": "千与千寻", "actor": "柊瑠美,入野自由,夏木真理", "releasetime": "2001-07-20(日本)", "score": "9.3"}
{"top": "9", "image_src": "https://p0.meituan.net/movie/46c29a8b8d8424bdda7715e6fd779c66235684.jpg@160w_220h_1e_1c", "name": "魂断蓝桥", "actor": "费雯·丽,罗伯特·泰勒,露塞尔·沃特森", "releasetime": "1940-05-17(美国)", "score": "9.2"}
{"top": "10", "image_src": "https://p0.meituan.net/movie/230e71d398e0c54730d58dc4bb6e4cca51662.jpg@160w_220h_1e_1c", "name": "乱世佳人", "actor": "费雯·丽,克拉克·盖博,奥利维娅·德哈维兰", "releasetime": "1939-12-15(美国)", "score": "9.1"}
写入文件

得到数据后最后将数据保存到文件,通过JOSN库的dumps()方法可以实现字典的序列化。因为这里要处理中文,将ensure_ascii参数设为False就可以保证输出结果是中文形式而不是Unicode编码。代码如下:

def write_to_file(content):
    with open("result.txt","a",encoding="utf-8") as f:
        f.write(json.dumps(content,ensure_ascii = False) + "
")
        f.close()

其中open()指定写入方式为a尾部写入,这是因为此时是for循环写入数据,如果用w写入只会保留最后一组的数据。或者在这之前打开文件,等写入完数据后再关闭也可以。
通过调用write_to_file()方法即可实现将字典写入到文本文件的过程。

main方法

实现main()方法接收一个offset值作为偏移量,然后构造URL进行爬取。代码如下:

def main(offset):
    url = "http://maoyan.com/board/4?offset=" + str(offset)
    html = get_page(url)
    for item in parse_page(html):
        print(item)
        write_of_file(item)
多线程分页爬取

上面实现了给main()传入一个offset值爬取单页10个电影的数据,接下来使用多线程来抓取整个TOP100的电影数据。

from multiprocessing import Pool  # 引入多线程模块

if __name__ == "__main__":
    #创建线程池
    pool = Pool()
    # pool.map第一个参数是函数,第二个参数是传递给函数的参数
    pool.map(main,[i*10 for i in range(10)])

Pool.map()函数第一个参数是函数,第二个参数是传递给函数的参数,在上面代码中是一个迭代器,将迭代器中的数字作为参数依次传入函数中。
注意:使用多线程爬取会导致最后写入到文件内的电影数据(top值)是乱序的,如需保证爬取到的电影信息写入到文件是按照top值排序的,放弃多线程将代码改为:

import time #引入时间模块
if __name__ == "__main__":
    for i in range(10):
        main(offset=i * 10)
        time.sleep(1)

为突破猫眼反爬虫机制(速度过快会无响应),上面代码增加了一个延时等待。

大功告成!完整代码如下:

import requests
import re
import time
import json
from requests.exceptions import RequestException
from multiprocessing import Pool

def get_page(url):
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"
    }
    response = requests.get(url,headers = headers)
    try:
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        print("request error")
        return None
def parse_page(html):
    pattern = re.compile("
.*?board-index.*?>(d+).*?data-src="(.*?)".*?name.*?a.*?>(.*?).*?star">(.*?)

" + ".*?releasetime">(.*?)

.*?integer">(.*?).*?fraction">(.*?).*?
",re.S) #re.S使.能匹配任意字符 items = pattern.findall(str(html)) for item in items: yield { "top":item[0], "image_src":item[1], "name":item[2], "actor":item[3].strip()[3:] if len(item[3]) > 3 else "", "releasetime":item[4].strip()[5:], "score":item[5] + item[6] } def write_to_file(content): with open("result.txt","a",encoding="utf-8") as f: f.write(json.dumps(content,ensure_ascii = False) + " ") f.close() def main(offset): url = "http://maoyan.com/board/4?offset=" + str(offset) html = get_page(url) for item in parse_page(html): print(item) write_to_file(item) # 如需保证电影顺序,则放弃使用多线程 # if __name__ == "__main__": # for i in range(10): # main(offset=i * 10) # time.sleep(1) if __name__ == "__main__": pool = Pool() pool.map(main,[i*10 for i in range(10)])

本文中的代码地址:https://github.com/grisse/Cra...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/42829.html

相关文章

  • Requests+正则达式爬取猫眼电影

    摘要:目标通过正则表达式爬取猫眼电影电影的排名名字电影封面图片主演上映时间猫眼评分,将爬取的内容写入文件中。为了加快爬取网页的速度,可以开启循环和多线程当需要爬取的信息很大时,这是一个不错的技巧。 目标 通过Request+正则表达式爬取猫眼电影TOP100电影的排名、名字、电影封面图片、主演、上映时间、猫眼评分,将爬取的内容写入文件中。 流程框架 进入到猫眼电影TOP100的页面,此时的U...

    30e8336b8229 评论0 收藏0
  • python正则达式简单爬虫入门+案例(爬取猫眼电影TOP榜)

    摘要:用迭代进行异步操作保存写入文件配置启动函数使用多进程加速一秒完成 用正则表达式实现一个简单的小爬虫 常用方法介绍 1、导入工具包 import requests #导入请求模块 from flask import json #导入json模块 from requests.exceptions import RequestException #异常捕捉模块 import re #导入正则...

    xiaowugui666 评论0 收藏0
  • Python3网络爬虫实战---27、Requests正则达式抓取猫眼电影排行

    摘要:所以我们如果想获取电影,只需要分开请求次,而次的参数设置为,,,,即可,这样我们获取不同的页面结果之后再用正则表达式提取出相关信息就可以得到的所有电影信息了。上一篇文章网络爬虫实战正则表达式下一篇文章网络爬虫实战解析库的使用 上一篇文章:Python3网络爬虫实战---26、正则表达式下一篇文章:Python3网络爬虫实战---28、解析库的使用:XPath 本节我们利用 Reque...

    SwordFly 评论0 收藏0
  • 从13万猫眼评论看看《流浪地球》到底怎么样

    摘要:今年的流浪地球这么火,通过爬取猫眼电影上网友对该片的评价如何。也许很多人在这天通过看流浪地球过节吧。 背景 最近几年猫眼电影越来越热门了,都差不多和豆瓣并驾齐驱了。今年的《流浪地球》这么火,通过爬取猫眼电影上网友对该片的评价如何。 爬取猫眼评论 找到评论网页地址 先打开猫眼官网找到《流浪地球》的介绍页面:https://maoyan.com/films/248906 showImg(h...

    lemanli 评论0 收藏0
  • 首次公开,整理12年积累的博客收藏夹,零距离展示《收藏夹吃灰》系列博客

    摘要:时间永远都过得那么快,一晃从年注册,到现在已经过去了年那些被我藏在收藏夹吃灰的文章,已经太多了,是时候把他们整理一下了。那是因为收藏夹太乱,橡皮擦给设置私密了,不收拾不好看呀。 ...

    Harriet666 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<