Python 爬虫 爬取豆瓣Top 250 更新

本文章的所有代码和相关文章, 仅用于经验技术交流分享,禁止将相关技术应用到不正当途径,滥用技术产生的风险与本人无关。
本文章是自己学习的一些记录。

爬取详细信息

之前写过一个爬取豆瓣top 250的博客 并且将海报的图片爬取下来进行保存。
这个更新的是我想把导演、主演、上映时间、影片类型都分开爬取下来,于是看了一些博客资料和文章 有了思路 但是大多数的我没看太懂 所以我自己摸索着把程序写了出来:
主要是那个影片信息里面嵌套的内容是这样的:
在这里插入图片描述
用xpath的话只能爬取p标签里面的文本内容和分开的内容,总之无法具体分开详细的信息,于是就得用正则表达式去详细的匹配;
像是这样:

 movie_director = re.findall(r"导演:(.*?);", response)
    a = "".join(movie_director).split("&nbsp")#因为使用的正则抓取下来的字符串含有&nbsp,使用split()函数进行切分
    movie_director = a[:25]
    if movie_director=="":
        movie_director=""
    else:
        movie_director=movie_director
    #主演,使用正则
    movie_main_act = re.findall("主演: (.*)<br>", response)
    movie_main_act = "".join(movie_main_act).split("...")
    if movie_main_act=="":
        movie_main_act=""
    else:
        movie_main_act=movie_main_act

使用正则以及一些python字符串、列表语法的处理去匹配到我们想要的内容:
上全部代码:

#coding=utf-8
import re
import requests
import json
from lxml import etree
import time
# 定义get请求函数
def get_page(url):
    #定义请求头headers
    try:
        headers={
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
        }
        #发送get请求
        res=requests.get(url=url,headers=headers)
        #判断请求是否成功
        if res.status_code==200:
            response=res.content.decode("utf-8")
            return response
        else:
            return False
    except:
        return False

#定义数据解析函数
def parse_data(html,url):
    #数据解析一些内容有的需要xpath 有的需要正则
    html = etree.HTML(html)
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
    }
    # 发送get请求
    res = requests.get(url=url, headers=headers)
    response = res.content.decode("utf-8")

    #电影名称
    movie_title=html.xpath("//div[@class='hd']//a//span[1]//text()")
    #电影评分
    movie_score=html.xpath('//div[@class="star"]//span[2]//text()')
    #电影排名
    movie_degree=html.xpath('//div[@class="item"]//div//em//text()')
    #电影海报地址
    movie_poster=html.xpath('//div[@class="pic"]//a//img/@src')
    #导演,使用正则
    movie_director = re.findall(r"导演:(.*?);", response)
    a = "".join(movie_director).split("&nbsp")#因为使用的正则抓取下来的字符串含有&nbsp,使用split()函数进行切分
    movie_director = a[:25]
    if movie_director=="":
        movie_director=""
    else:
        movie_director=movie_director
    #主演,使用正则
    movie_main_act = re.findall("主演: (.*)<br>", response)
    movie_main_act = "".join(movie_main_act).split("...")
    if movie_main_act=="":
        movie_main_act=""
    else:
        movie_main_act=movie_main_act
    #上映日期
    movie_datatime= re.findall(r"(\d*)&nbsp;", response)
    b = "".join(movie_datatime)#转化为字符串
    movie_datatime = [b[i:i + 4] for i in range(0, len(b), 4)]#转换的字符串是一对数字如199419931994....,所以进行切分 4个一切就是年份
    if movie_datatime=="":
        movie_datatime=""
    else:
        movie_datatime=movie_datatime
    #电影国家
    movie_country= re.findall("&nbsp;/&nbsp;(.*?)&nbsp;", response)
    #电影类型,这个原网页写的有点不好爬   我看了网上其他的也都看不明白   所以就
    #自己用这样的方法写出来 然后就匹配出来了,可定还有简便的方法 ,以后学习继续改进
    movie_type= html.xpath("//div[@class='bd']/p/text()[2]")
    n = ''.join([' '.join([i.strip() for i in price.strip().split('\n')]) for price in movie_type][::2]).split("\xa0/\xa0")#转换为字符串进行切分
    #n 返回['1994', '美国', '犯罪 剧情1993', '中国大陆 中国香港', '剧情 爱情 同性1994', '美国', '剧情 爱情1994', '法国 美国', '剧情 动作 犯罪1997', '意大利', '剧情 喜剧 爱情 战争1997', '美国', '剧情 爱情 灾难2001', '日本', '剧情 动画 奇幻1993', '美国', '剧情 历史 战争2010', '美国 英国', '剧情 科幻 悬疑 冒险2009', '美国 英国', '剧情1998', '意大利', '剧情 音乐1998', '美国', '剧情 科幻2009', '印度', '剧情 喜剧 爱情 歌舞2008', '美国', '科幻 动画 冒险2004', '法国 瑞士 德国', '剧情 音乐2014', '美国 英国 加拿大 冰岛', '剧情 科幻 冒险1995', '中国香港 中国大陆', '喜剧 爱情 奇幻 古装2011', '韩国', '剧情2016', '美国', '喜剧 动画 冒险2002', '中国香港', '剧情 犯罪 悬疑1988', '日本', '动画 奇幻 冒险1972', '美国', '剧情 犯罪2006', '美国', '剧情 传记 家庭2010', '美国', '剧情 喜剧 爱情2011', '法国', '剧情 喜剧']
    l = n[2::2]#因为上面的n列表我们包含的电影类型,所以n[2::2]操作把包含类型都取出来
    o = ''.join(l)#转换为字符串
    h = re.sub("\d{4}", ";", o)#使用正则将数字全都用;符号代替
    #h 返回为 犯罪 剧情;剧情 爱情 同性;剧情 爱情;剧情 动作 犯罪;剧情 喜剧 爱情 战争;剧情 爱情 灾难;剧情 动画 奇幻;剧情 历史 战争;剧情 科幻 悬疑 冒险;剧情;剧情 音乐;剧情 科幻;剧情 喜剧 爱情 歌舞;科幻 动画 冒险;剧情 音乐;剧情 科幻 冒险;喜剧 爱情 奇幻 古装;剧情;喜剧 动画 冒险;剧情 犯罪 悬疑;动画 奇幻 冒险;剧情 犯罪;剧情 传记 家庭;剧情 喜剧 爱情;剧情 喜剧
    movie_type = h.lstrip("\n")#这个之前打印的最左边有一个\n符号  所以使用lstrip()函数去掉
    movie_type = movie_type.split(";")#然后用字符串split()函数以;符号进行切分
    if movie_type=="":
        movie_type=""
    else:
        movie_type=movie_type
    #movie_type 最终的返回  ['犯罪 剧情', '剧情 爱情 同性', '剧情 爱情', '剧情 动作 犯罪', '剧情 喜剧 爱情 战争', '剧情 爱情 灾难', '剧情 动画 奇幻', '剧情 历史 战争', '剧情 科幻 悬疑 冒险', '剧情', '剧情 音乐', '剧情 科幻', '剧情 喜剧 爱情 歌舞', '科幻 动画 冒险', '剧情 音乐', '剧情 科幻 冒险', '喜剧 爱情 奇幻 古装', '剧情', '喜剧 动画 冒险', '剧情 犯罪 悬疑', '动画 奇幻 冒险', '剧情 犯罪', '剧情 传记 家庭', '剧情 喜剧 爱情', '剧情 喜剧']
    datalist=list(zip(movie_title,movie_score,movie_degree,movie_director,movie_main_act,movie_poster,movie_datatime,movie_country,movie_type))
    total_data=[{"电影名称":i[0],"电影评分":i[1],"电影排名":i[2],"导演":i[3],"主演":i[4],"电影海报地址":i[5],"上映日期":i[6],"电影国家":i[7],"电影类型":i[8],} for i in datalist]
    # print(total_data)
    for s in total_data:
        print(s)
    # 将爬取分数据写入文件中
        with open("./zuizhongdouban.json",'a+',encoding='utf-8') as f:
            f.write(json.dumps(s,ensure_ascii=False))
            f.write("\n")


def main(num):
    #定义url
    url=f'https://movie.douban.com/top250?start={num}'
    # 调用发送get请求函数
    html=get_page(url)
    # 如果发送请求成功,执行解析数据函数
    if html:
        parse_data(html,url)


if __name__=="__main__":
    for i in range(10):
        print(f"正在爬取第{i}页数据")
        main(i*25)
        time.sleep(2)

这里将所有的代码贴出来了,将爬取的数据写进json文件当中,爬取的结果:
在这里插入图片描述
在这里插入图片描述
这样就可以将具体的详细信息爬取下来了
json文件显示:
在这里插入图片描述
在这里插入图片描述
在程序里面提取这些信息的时候,主要是会用到split()函数和strip()函数,进行字符串的切分和剔除不必要的信息。
同时还有字符串与列表之间的相互转换

爬取成功了 但是出现了一个bug 这个目前还没有解决,就是本来应该爬取一共是250条数据,但是爬取后发现有10几条数据漏掉了 我尝试了几种检查的方法,发现正常的话单页的数据都可以爬取下来,我发现有的简介上没有主演:但是我加了判断:

    if movie_main_act=="":
        movie_main_act=""
    else:
        movie_main_act=movie_main_act

这样的话即使没有信息的话也可以返回空的内容,以至于使用zip()函数的时候都可以并行匹配。
这个还未解决 不过总算是把详细的信息爬下来了 记录一下

有知道这个bug怎么解决的大佬欢迎在评论区指点。

继续学习

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值