欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python爬虫学习案例之抓取猫眼电影排行Top100

程序员文章站 2022-06-09 17:10:59
目前在自学python爬虫,接下来运用学习了的requests库和正则表达式实操一下Python爬虫初学者经常训练的一个小实战案例——爬取猫眼电影排行Top100抓取分析首先我们打开抓取的目标站点https://maoyan.com/board/4同时此时页面的URL为https://maoyan.com/board/4?offset=0我们将网页滚到最下方,发现有分页的列表,直接点击第2页,观察页面的URL和内容发生了变化,URL变为了https://maoyan.com/board/4?of...

目前在自学python爬虫,接下来运用学习了的requests库和正则表达式实操一下Python爬虫初学者经常训练的一个小实战案例——爬取猫眼电影排行Top100

抓取分析

首先我们打开抓取的目标站点https://maoyan.com/board/4

Python爬虫学习案例之抓取猫眼电影排行Top100

同时此时页面的URL为https://maoyan.com/board/4?offset=0

Python爬虫学习案例之抓取猫眼电影排行Top100

我们将网页滚到最下方,发现有分页的列表,直接点击第2页,观察页面的URL和内容发生了变化,URL变为了https://maoyan.com/board/4?offset=10,目前显示的排名为11~20的电影。

Python爬虫学习案例之抓取猫眼电影排行Top100

我们点击第3页,URL变为了https://maoyan.com/board/4?offset=20,显示的排名为21~30的电影。
Python爬虫学习案例之抓取猫眼电影排行Top100
因此我们可以发现规律,offset代表偏移量,如果偏移量为n,则显示的电影序号为n+1到n+10,每页显示10个。所有想要获取Top100的电影,需要循环10次。

接下来就i是分析首页的源代码了,在开发者工具中的Network监听组件中查看源代码。如图所示
Python爬虫学习案例之抓取猫眼电影排行Top100
也可以通过request.get()方法获取首页的源代码

import requests
import re

def get_one_page(url):
   headers = {
      'User-Agent':'Mozilla/5.0',
      }
   response = requests.get(url,headers=headers)
   if response.status_code == 200:
      return response.text
   else:
      return None

def main(offset):
   base_url = 'https://maoyan.com/board/4?offset='
   url = base_url+str(offset)
   html = get_one_page(url)
   print(html)

if __name__=='__main__':
   main(0)

输出如下:(取了其中一部分)

                <dd>
                        <i class="board-index board-index-1">1</i>
    <a href="/films/1375" title="活着" class="image-link" data-act="boarditem-click" data-val="{movieId:1375}">
      <img src="//s3plus.meituan.net/v1/mss_e2821d7f0cfe4ac1bf9202ecf9590e67/cdn-prod/file:5788b470/image/loading_2.e3d934bf.png" alt="" class="poster-default" />
      <img data-src="https://p0.meituan.net/movie/4c41068ef7608c1d4fbfbe6016e589f7204391.jpg@160w_220h_1e_1c" alt="活着" class="board-img" />
    </a>
    <div class="board-item-main">
      <div class="board-item-content">
              <div class="movie-item-info">
        <p class="name"><a href="/films/1375" title="活着" data-act="boarditem-click" data-val="{movieId:1375}">活着</a></p>
        <p class="star">
                主演:葛优,巩俐,牛犇(bēn)
        </p>
<p class="releasetime">上映时间:1994-05-17(法国)</p>    </div>
    <div class="movie-item-number score-num">
<p class="score"><i class="integer">9.</i><i class="fraction">0</i></p>        
    </div>

      </div>
    </div>

                </dd>

可以看到,一部电影的信息对应的源代码就是一个dd节点,我们的目标是提取电影的排名、名称、时间、评分、图片等信息。接下来就是设计正则表达式了

正则提取

排名

根据上文源代码,我们可以发现排名信息是在class为board-index的i节点内<i class="board-index board-index-1">1</i>,那么我们就设计正则表达式为<dd>.*?board-index.*?>(\d+)</i>

图片

同样的,上述的a节点中有两个img节点对应的是图片的信息,第二个img节点的data-src属性是图片的链接<img data-src="https://p0.meituan.net/movie/4c41068ef7608c1d4fbfbe6016e589f7204391.jpg@160w_220h_1e_1c" alt="活着" class="board-img" />,因此更新正则表达式为<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)"

名称

电影的名称在后面的p节点内,class为name,即<p class="name"><a href="/films/1375" title="活着" data-act="boarditem-click" data-val="{movieId:1375}">活着</a></p>。所以可以用name做一个标志位,然后进一步提取到其内a节点的正文内容,此时正则表达式改写如下:<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>

主演

主演提取思路同上,根据

    <p class="star">
            主演:葛优,巩俐,牛犇(bēn)
    </p>

则修改正则表达式为:<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>

时间

时间提取思路同上,根据<p class="releasetime">上映时间:1994-05-17(法国)</p>修改正则表达式为:<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>

评分

评分提取思路同上,最终正则表达式为:<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>

接下来就是编写提取页面信息的时候啦!

总代码如下:

import requests
import json
import time
import re
import random

def get_one_page(url):
   
   headers = [{
      'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1',
      },{
      'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0',
      },{
      'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
      }]
   count = random.randint(0,2)
   response = requests.get(url,headers=headers[count])
   if response.status_code == 200:
      return response.text
   else:
      return None

def parse_one_page(html):
   pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>',re.S)
   items = re.findall(pattern,html)
   for item in items:
      yield{
         'index':item[0],
         'image_url':item[1],
         'title':item[2].strip(),
         'actor':item[3].strip()[3:],
         'time':item[4].strip()[5:],
         'score':item[5].strip()+item[6].strip()
         }

def write_to_file(content):
   with open('result.txt','a',encoding='utf-8') as f:
      f.write(json.dumps(content,ensure_ascii=False)+'\n')
      
def main(offset):
   base_url = 'https://maoyan.com/board/4?offset='
   url = base_url+str(offset)
   html = get_one_page(url)
   for item in parse_one_page(html):
      print(item)
      write_to_file(item)

if __name__=='__main__':
   for i in range(10):
      main(offset = i*10)
      time.sleep(3)

下面针对以上程序进行简单讲解,中心思想就是循环调用main()函数,通过更改offset偏移量来对10个页面进行遍历访问,访问一个页面后如果响应状态码为200则返回响应信息,并通过parse_one_page(html)对返回的信息进行正则提取以及结果处理,同时将获取的结果写入文件。

其中,parse_one_page(html)中的下面的代码可能有些不好理解

   for item in items:
      yield{
         'index':item[0],
         'image_url':item[1],
         'title':item[2].strip(),
         'actor':item[3].strip()[3:],
         'time':item[4].strip()[5:],
         'score':item[5].strip()+item[6].strip()
         }

因为函数中带有yield,我们可以把它(该函数)看作一个生成器,并且当执行到yield的时候,函数将会将item的数据处理为字典类型打包返回,返回给了main(offset)的print(item),然后将该部分item写入文件,当执行下一次 for item in parse_one_page(html)时,程序跳入parse_one_page(html)的上次离开的地方,即执行下一次parse_one_page(html)的for item in items循环,而并不是从函数开头执行。

如下图:
Python爬虫学习案例之抓取猫眼电影排行Top100
对于**write_to_file(content)**函数,这里就是通过JSON库的dumps()方法实现字典的序列化,并指定ensure_ascii参数为Fasle,这样就可以保证输出结果是中文形式而不是Unicode编码。

最后,成功爬取到了Top100,是真真切切感受到了爬虫的强大,加利用真的能简化很多事情呢!

保存的result.txt文件输出打印信息
Python爬虫学习案例之抓取猫眼电影排行Top100
Python爬虫学习案例之抓取猫眼电影排行Top100

本文地址:https://blog.csdn.net/qq_42642142/article/details/107655245