零基础爬虫实战(Python):抓取豆瓣电影TOP250

​ 学习了《简明Python教程》,然后想着实战一下,搜索了一些资料,然后对豆瓣电影排行250进行了一个抓取,后续还会对数据进行一些分析。

​ 这篇文章主要是对抓取豆瓣电影top250过程的一个梳理,方便日后自己查阅,也希望可以方便到有需要的人。

​ 下面是整个抓取过程的思维导图:

爬取豆瓣电影TOP250.png

1. 生成URL信息

​ 首先观察豆瓣电影TOP250的网页地址,多点开几页,就能发现规律。每一页都是展示了25个电影。

2. 分析网页标签

​ 这个就是对网页html文件的解析了,可以先在网页中浏览目标信息,然后在网页的源码中通过搜索查找到相应的标签。最后一定要搞清楚定位每一个目标信息标签的方式。

​ 我在这是采用的是BeautifulSoup对html进行的解析。

3. 请求网页数据

​ 我是使用urllib.request中的urlopen()方法对网页进行请求的。

urlopen(url).read().decode('utf-8')

​ urlopen(url)获取到的是HTTPResponse对象,然后调用read()方法获得网页的字节数据,字节数据没法直接处理,所以最后调用decode('utf-8')方法将获取的字节对象编码成文本字符串(string)

4. 存储信息

​ 先把数据生成pandas库的DataFrame对象,然后调用其to_csv()方法将数据存储到csv文件中,非常的方便。

完整的代码

​ 算是自己完成了第一个小的爬虫程序,以后会在此基础上不断的扩展与完善。下面是获取豆瓣电影TOP250的Python完整代码。

# encoding=utf-8

from collections import defaultdict
from urllib.request import urlopen
from bs4 import BeautifulSoup
import pandas as pd
import time
import re


class DoubanMovieTop250:
    # 生成url和相应存储最终数据的容器
    def __init__(self):
        self.top250_urls = ['https://movie.douban.com/top250?start={0}&filter='.format(i * 25) for i in range(10)]
        self.data = defaultdict(list)
        self.columns = ['title', 'link', 'score', 'score_cnt', 'top_no', 'directors', 'writers', 'actors', 'types',
                        'edit_location', 'language', 'dates', 'play_location', 'length', 'rating_per',
                         'betters', 'had_seen', 'want_see', 'tags', 'review', 'ask', 'discussion']
        self.df=None

    def get_info(self):
        for url in self.top250_urls:
            # 将获取的网页封装成BeautifulSoup
            print(url)
            html = urlopen(url).read().decode('utf-8')

            bsobj = BeautifulSoup(html)

            # 开始解析网页中的数据
            main = bsobj.find('ol', {'class': 'grid_view'})


            # 标题及链接信息
            title_obj = main.findAll('div', {'class': 'hd'})
            titles = [ i.find('span', {'class': 'title'}).text for i in title_obj]
            links = [ i.find('a')['href'] for i in title_obj]

            # 评分信息
            score_obj = main.findAll('div', {'class': 'star'})
            scores = [i.find('span', {'class': 'rating_num', 'property': 'v:average'}).text for i in score_obj]
            score_cnts = [ i.findAll('span')[-1].text for i in score_obj]

            # 将解析到的数据存入到容器中
            for title, link, score, score_cnt in zip(titles, links, scores, score_cnts):
                self.data[title].extend([title, link, score, score_cnt])
                # 解析更多、更详细的信息
                more_data = self.get_more_info(link)
                self.data[title].extend(more_data)
                print(self.data[title])
                print(len(self.data))
                time.sleep(1)

    def get_more_info(self, link):
        html = urlopen(link).read().decode('utf-8')
        bsobj = BeautifulSoup(html)

        # 榜单排名 top_no
        top_no = bsobj.find('span', {'class': 'top250-no'}).text

        # 导演 directors
        main = bsobj.find('div', {'id': 'info'})
        directors = [i.text for i in main.findAll('a', {'rel': 'v:directedBy'})]

        # 编剧 writers 可能没有编剧
        try:
            writers = [i.text for i in main.findAll('span', {'class': 'attrs'})[1].findAll('a')]
        except Exception as ex:
            writers = []
            print(ex)

        # 主演 actors 可能没有主演
        try:
            actors_obj = main.findAll('a', {'rel': 'v:starring'})
            actors = [i.text for i in actors_obj]
        except Exception as ex:
            actors = []
            print(ex)

        # 类型 types
        types_obj = main.findAll('span', {'property': 'v:genre'})
        types = [i.text for i in types_obj]

        # 制片地区 edit_location
        pattern = re.compile('地区:(.*)\n语言', re.S)
        edit_location = re.findall(pattern, main.text)[0]

        # 语言 language
        pattern2 = re.compile('语言:(.*)\n上映日期', re.S)
        language = re.findall(pattern2, main.text)[0]


        # 上映日期和地区  dates play_location
        date_boj = main.findAll('span', {'property': 'v:initialReleaseDate'})
        dates = [i['content'].split('(')[0] for i in date_boj]
        play_location = [i['content'].split('(')[1] for i in date_boj]

        # 片长 length
        length = main.find('span', {'property': 'v:runtime'})['content']

        # 5星到1星的比例 rating_per 一共是5个数字
        rating_per = [i.text for i in bsobj.findAll('span', {'class': 'rating_per'})]

        # 好于 betters
        better_obj = bsobj.find('div', {'class': 'rating_betterthan'}).findAll('a')
        betters = [i.text for i in better_obj]


        # 想看/看过 had_seen want_see
        fit_obj = bsobj.find('div', {'class': 'subject-others-interests-ft'})
        had_seen = fit_obj.find('a').text[:-3]
        want_see = fit_obj.findAll('a')[1].text[:-3]

        # 标签 tags
        tags = [i.text for i in bsobj.find('div', {'class': 'tags-body'}).findAll('a')]

        # 短评 review  (有多少个短评)
        review = bsobj.find('div', {'id': 'comments-section'}).find('h2').find('a').text

        # 问题 ask (有多少个问题)
        ask = bsobj.find('div', {'id': 'askmatrix'}).find('a').text.strip()

        # 讨论 discussion (有多少个讨论)
        discussion = bsobj.find('p', {'class': 'pl', 'align':'right'}).find('a').text.strip().split('(')[1][2:-2]

        more_data=[top_no, directors, writers, actors, types, edit_location, language, dates, play_location, length, rating_per, betters, had_seen, want_see,tags, review, ask, discussion]
        return more_data

    # 存储数据到csv文件
    def dump_data(self):
        data = []
        for title, value in self.data.items():
            data.append(value)
            self.df=pd.DataFrame(data, columns=self.columns)
            self.df.to_csv('exercise_douban_movie_Top250.csv')


if __name__ == '__main__':
    douban = DoubanMovieTop250()
    douban.get_info()
    douban.dump_data()

参看资料:零基础Python爬虫实战:豆瓣电影TOP250

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容