l2430478 发表于 2021-1-14 13:22

Python自学笔记(10)----------尝试Requests TOP250电影数据

本帖最后由 l2430478 于 2021-1-14 15:00 编辑

----------------再次强调,我自学笔记前6个可以直接跳过,学爬虫,直接从笔记七开始就行.

我看豆瓣电影TOP250是爬虫新人必爬对象,我也尝试爬取。
网页地址为:https://movie.douban.com/top250。
在此爬虫中,需要将请求头定制为实际浏览器的请求头。
1、网站分析
打开豆瓣电影TOP250的网站,使用“检查“功能查看该网页的请求头。


把需要的数据复制出来,

User-Agent:
Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36

Host:
movie.douban.com
然后根据以上信息,做出自己的请求头
    headers = { 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36',
'Host: movie.douban.com '}

TOP250有个特点,每页只显示25个电影,如果要获取所有的250页电影,就需要获取总共10页的内容。
通过单击第二页可以发现网页地址变成了:https://movie.douban.com/top250?start=25第三页的地址为:https://movie.douban.com/top250?start=50。规律是每多一页,就给网页地址的start参数加上25。
通过以上分析发现,可以使用requests获取电影网页的代码,并利用for循环翻页。
仔细扣,又发现https://movie.douban.com/top250?start=0&filter= 也能看到排行。
尝试想用上几个帖子写的代码进行headers进行请求,结果返回的不是200,说明该网也进行了反爬。
询问朋友,他让我加一个timeout参数
html = requests.get(url, headers=headers,timeout=30)
请求成功返回状态码200
print(html.status_code)
我们这次在网页上点击查看源代码,发现每个 <li> </li>之间为每个电影的所有信息。而 </li>结束之后,即为下一个电影<li>的开始。也就是说,每个 <li> </li>是独立的,我们只需要把这250个 <li> </li>的信息提取出来即可。

继续深入分析可知,我们需要的信息都被<div class="info">所包含

那我们分成一小块一小块来解决问题,先用xpath解析出class属性为info的div块
root.xpath('//div[@class="info"]')
继续深入分析,每段代码的含义如下:
                # 影片名称
      title = InformationBlock.xpath('div[@class="hd"]/a/span[@class="title"]/text()')
      # print(title)

      info = InformationBlock.xpath('div[@class="bd"]/p/text()')
      # print(type(info))

      directorAndStarring = str(info).split("   ")
      # 导演
      director = directorAndStarring.replace(" ", "").replace("\n", "").replace("导演:", "")
      
      # 主演
      try:
            Starring = directorAndStarring.replace(" ", "").replace("\n", "").replace("主演:", "")
      except :
            Starring = "NULL"

      # 上映日期
      date = info.replace(" ", "").replace("\n", "").split("/")

      # 制片国家
      country = info.replace(" ", "").replace("\n", "").split("/")

      # 影片类型
      geners = info.replace(" ", "").replace("\n", "").split("/")

      # 评分
      rate = InformationBlock.xpath('div[@class="bd"]/div/span/text()')

      # 评论人数
      comCount = InformationBlock.xpath('div[@class="bd"]/div/span/text()').replace("人评价", "")


这样,我们就找到需要的信息了,现在就可以获取信息保存在本地,代码如下:
datas = (("{},{},{},{},{},{},{},{},{}").format(Top, title, director, Starring, rate, date, country, geners, comCount))
      with open("doubanMovie.csv", "a", newline="", encoding="utf_8_sig") as f:
            f.write(datas+"\n")


Top为设定的全局变量
此文件使用追加模式,即此处的open()函数第二个参数为"a"
encoding编码格式,此处有坑,之前笔者用"utf-8"格式向csv文件写入数据,csv文件打开后中文乱码,查找了不少资料,最后发现使用"utf_8_sig"格式有效解决问题
以上三步可以完成单页的爬取,但是Top250被分成了10页,让我们看看它剩下几页url的规律
第一页
https://movie.douban.com/top250?start=0&filter=
第二页
https://movie.douban.com/top250?start=25&filter=
第三页
https://movie.douban.com/top250?start=50&filter=
...
最后一页
https://movie.douban.com/top250?start=225&filter=


每一页url的start= 后跟的参数从0开始,每页增加25,最大为225,OK分析完成
# 翻页
def nextPage():
    for i in range(0, 250, 25):
      url = 'https://movie.douban.com/top250?start={}&filter='.format(i)
      getInfo(url)




其代码如下:
"""
电影Top250主页 (需翻页;翻页url:("https://movie.douban.com/top250?start={}&filter=").format(i),i = i + 25)
获取信息存储于csv文件中
"""
from lxml import etree
import requests

headers = {"User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                         'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
         }
Top = 1


# 获取信息
def getInfo(url):
    html = requests.get(url, headers=headers, timeout=30)
    # print(html.status_code)
    root = etree.HTML(html.content)

    # 我们所需要的所有的信息都在<div class="info">块中
    for InformationBlock in root.xpath('//div[@class="info"]'):
      # 影片名称
      title = InformationBlock.xpath('div[@class="hd"]/a/span[@class="title"]/text()')
      # print(title)

      # <div class="bd">块,导演、演员、上映时间、制片国家、影片类型在一个<p>里
      info = InformationBlock.xpath('div[@class="bd"]/p/text()')
      # print(type(info))
      '''
                导演主演 info
      '''
      directorAndStarring = str(info).split("   ")
      # 导演
      director = directorAndStarring.replace(" ", "").replace("\n", "").replace("导演:", "")
      # 主演
      try:
            Starring = directorAndStarring.replace(" ", "").replace("\n", "").replace("主演:", "")
      except :
            Starring = "NULL"

      '''
      上映日期、制片国家、影片类型 info
      '''
      # 上映日期
      date = info.replace(" ", "").replace("\n", "").split("/")

      # 制片国家
      country = info.replace(" ", "").replace("\n", "").split("/")

      # 影片类型
      geners = info.replace(" ", "").replace("\n", "").split("/")

      # 评分
      rate = InformationBlock.xpath('div[@class="bd"]/div/span/text()')

      # 评论人数
      comCount = InformationBlock.xpath('div[@class="bd"]/div/span/text()').replace("人评价", "")

      global Top
      # 打印结果看看
      print(Top, title, director, Starring, rate, date, country, geners, comCount)
      print("---------------------------------------------------------")
      datas = (("{},{},{},{},{},{},{},{},{}").format(Top, title, director, Starring, rate, date, country, geners, comCount))
      with open("doubanMovie.csv", "a", newline="", encoding="utf_8_sig") as f:
            f.write(datas+"\n")
      Top += 1


# 翻页
def nextPage():
    for i in range(0, 250, 25):
      url = 'https://movie.douban.com/top250?start={}&filter='.format(i)
      getInfo(url)


if __name__ == '__main__':
      # 给文件加头部标题
    with open("doubanMovie.csv", "w", newline="", encoding="utf_8_sig") as f:
      f.write("Top,title,director,Starring,rate,date,country,geners,comCount"+"\n")
    nextPage()







   





------------------------几个小白常识
|||from lxml import etree   #表示是 从 lxml 这个库中导入 etree      (需要安装 lxml包)
|||import requests#表示是调用requests包
|||headers = 一串字符就是模拟用户访问防网址反爬 你就调取不了数据
|||如果你把Top = 1 去了爬取的将是继续爬,举例你第一次爬取的是1-250,那么删除Top = 1后,第二次将从251开始继续存档,但数据还是这相同的250个。
|||def getInfo(url):代表定义一个函数,我们可以定义一个由自己想要功能的函数,以下是简单的规则:1.函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。2.任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
3.函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。4.函数内容以冒号起始,并且缩进。5.return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。



bevirus 发表于 2021-1-14 13:36

&#128077; 顶一下

hacksz 发表于 2021-1-14 13:37

赞,学习一下{:301_978:}

VIP007 发表于 2021-1-14 13:37

这个学的太快来赞学习了

andyfky 发表于 2021-1-14 14:10

高手啊,努力。

alinjx 发表于 2021-1-14 14:13

厉害,一直想学,但是工作又没时间

Ldfd 发表于 2021-1-14 14:21

不,我爬的是吾爱{:301_986:}

迦南圣经 发表于 2021-1-14 14:37

大佬大佬,爬虫

shieep 发表于 2021-1-14 14:48

每页只显示25个电影,如果要获取所有的250页电影,就需要获取总共10页的内容。

郭小生 发表于 2021-1-14 14:49

OSError: %1 不是有效的 Win32 应用程序。求助大佬!!!我这咋办
页: [1] 2
查看完整版本: Python自学笔记(10)----------尝试Requests TOP250电影数据