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,这里必须加,估计是网站做了限制,直接爬的话会失败,可能认出请求链接的不是一个人而是一只虫了
    代码中注释写得很详细,不再过多描述了

  • 相关阅读:
    每日日报2020.12.1
    每日日报2020.11.30
    981. Time Based Key-Value Store
    1146. Snapshot Array
    565. Array Nesting
    79. Word Search
    43. Multiply Strings
    Largest value of the expression
    1014. Best Sightseeing Pair
    562. Longest Line of Consecutive One in Matrix
  • 原文地址:https://www.cnblogs.com/hanmk/p/9218080.html
Copyright © 2011-2022 走看看