zoukankan      html  css  js  c++  java
  • 猫眼电影爬取(一):requests+正则,并将数据存储到mysql数据库

    前面讲了如何通过pymysql操作数据库,这次写一个爬虫来提取信息,并将数据存储到mysql数据库

    1.爬取目标

    爬取猫眼电影TOP100榜单
    要提取的信息包括:电影排名、电影名称、上映时间、分数

    2.分析网页HTML源码

    可以看到每部电影信息都被包裹在一对<dd>...</dd>标签中,所以我们只需提取出一个标签对中的上述信息即可。使用正则表达式提取

    3. 完整过程

    这个例子有2个关键点:正则编写和数据处理(写进mysql数据库)
    (1) 正则表达式的编写

        pattern = re.compile(r'<dd>.*?<i.*?>(d+)</i>.*?'  # 匹配电影排名(加个?表示非贪婪匹配,不是匹配0次或1次)
                             r'<p class="name"><a.*?data-val=".*?">(.*?)'  # 匹配电影名称
                             r'</a>.*?<p.*?class="releasetime">(.*?)</p>'  # 匹配上映时间
                             r'.*?<i.*?"integer">(.*?)</i>'   # 匹配分数的整数位
                             r'.*?<i.*?"fraction">(.*?)</i>.*?</dd>', re.S)  # 匹配分数小数位,re.S表示跨行匹配
        m = pattern.findall(html)
        # print(m)
    

    使用findall()方法来匹配所有符合规则的字符,返回一个列表,下面是其中一页的匹配结果

    (2)完整代码,注意get_data()函数是如何处理数据,然后通过write_sql()函数是写入数据库的

    # coding: utf-8
    # author: hmk
    
    import requests
    import re
    import pymysql
    
    def get_html(url, header):
        response = requests.get(url, headers=header)
        if response.status_code == 200:
            return response.text
        else:
            return None
    
    def get_data(html, list_data):
        pattern = re.compile(r'<dd>.*?<i.*?>(d+)</i>.*?'  # 匹配电影排名
                             r'<p class="name"><a.*?data-val=".*?">(.*?)'  # 匹配电影名称
                             r'</a>.*?<p.*?class="releasetime">(.*?)</p>'  # 匹配上映时间
                             r'.*?<i.*?"integer">(.*?)</i>'  # 匹配分数的整数位
                             r'.*?<i.*?"fraction">(.*?)</i>.*?</dd>', re.S)  # 匹配分数小数位
        m = pattern.findall(html)
        for i in m:  # 因为匹配到的所有结果会以列表形式返回,每部电影信息以元组形式保存,所以可以迭代处理每组电影信息
            ranking = i[0]  # 提取一组电影信息中的排名
            movie = i[1]  # 提取一组电影信息中的名称
            release_time = i[2]  # 提取一组电影信息中的上映时间
            score = i[3] + i[4]  # 提取一组电影信息中的分数,这里把分数的整数部分和小数部分拼在一起
            list_data.append([ranking, movie, release_time, score])  # 每提取一组电影信息就放到一个列表中,同时追加到一个大列表里,这样最后得到的大列表就包含所有电影信息
    
    def write_sql(data):
        conn = pymysql.connect(host='localhost',
                               user='root',
                               password='123456',
                               db='test',
                               charset='utf8')
        cur = conn.cursor()
    
        for i in data:
            """这里的data参数是指正则匹配并处理后的列表数据(是一个大列表,包含所有电影信息,每个电影信息都存在各自的一个列表中;
            对大列表进行迭代,提取每组电影信息,这样提取到的每组电影信息都是一个小列表,然后就可以把每组电影信息写入数据库了)"""
            movie = i  # 每组电影信息,这里可以看做是准备插入数据库的每组电影数据
            sql = "insert into maoyan_movie(ranking,movie,release_time,score) values(%s, %s, %s, %s)"  # sql插入语句
            try:
                cur.execute(sql, movie)  # 执行sql语句,movie即是指要插入数据库的数据
                conn.commit()  # 插入完成后,不要忘记提交操作
                print('导入成功')
            except:
                print('导入失败')
        cur.close()  # 关闭游标
        conn.close()  # 关闭连接
    
    def main():
        start_url = 'http://maoyan.com/board/4'
        depth = 10  # 爬取深度(翻页)
        header = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
                  "Accept-Encoding": "gzip, deflate, sdch",
                  "Accept-Language": "zh-CN,zh;q=0.8",
                  "Cache-Control": "max-age=0",
                  "Connection": "keep-alive",
                  "Host": "maoyan.com",
                  "Referer": "http://maoyan.com/board",
                  "Upgrade-Insecure-Requests": "1",
                  "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36"}
    
        for i in range(depth):
            url = start_url + '?offset=' + str(10 * i)
            html = get_html(url, header)
            list_data = []
            get_data(html, list_data)
            write_sql(list_data)
            #print(list_data)
            # for i in list_data:
            #     t = i
            #     print(t)
    
    if __name__ == "__main__":
        main()
    
    


    注意一点,在请求url时,加了headers,这里必须加,估计是网站做了限制,直接爬的话会失败,可能认出请求链接的不是一个人而是一只虫了
    代码中注释写得很详细,不再过多描述了

  • 相关阅读:
    【刷题-LeetCode】204. Count Primes
    【刷题-LeetCode】205. Isomorphic Strings
    【刷题-LeetCode】207. Course Schedule
    剑指offer题解——找出数组中重复的数字
    关于c++中vector操作
    动态规划算法
    分治算法
    从零学python——组合数据类型
    从零学python—PyInstaller库的介绍
    从零学python——代码复用与函数递归
  • 原文地址:https://www.cnblogs.com/hanmk/p/9218080.html
Copyright © 2011-2022 走看看