• 几种方式保存爬虫爬取的数据 Python


    以美团烤肉为例,将爬取的数据进行保存。

    第一种:csv。

    新建一个csv文档,利用字典写入器写入头,然后把爬取好的数据进行字典构造,然后将字典逐条写入到csv文档里。

     1 """
     2     爬取美团烤肉
     3 """
     4 import pprint
     5 import csv
     6 import parsel
     7 import requests
     8 import json
     9 
    10 f = open('美团烤肉.csv', mode='a', encoding='utf-8-sig', newline='')
    11 csvWriter = csv.DictWriter(f, fieldnames=[
    12         '商铺id',
    13         '商铺名称',
    14         '烤肉类型',
    15         '评论人数',
    16         '平均消费',
    17         '商铺评分',
    18         '所在商圈',
    19         '详情页',
    20 ])
    21 csvWriter.writeheader() # 写入头
    22 
    23 headers = {
    24     'referer':'https://xxz.meituan.com/', # 这个叫防盗链,也叫来路,没有这个可能不会返回正常的json数据
    25     'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36',
    26 }
    27 
    28 
    29 for page in range(32, 620 + 1, 32):
    30 # 原始请求url= https://apimobile.meituan.com/group/v4/poi/pcsearch/110?uuid=f7325d6be06f44019907.1639106132.1.0.0&userid=394536385&limit=32&offset=64&cateId=-1&q=烤肉&token=mKqO1rGk3adC-dG4fspmVCJj-bgAAAAAhA8AAPVPiOhDFB1UirWrXZHX_ZEM-6qsRE4yHPX1o2RbzI9csT0G-CikXFP8TPrDZj0EwQ
    31 # url中?后面的都是参数,下面来构建参数
    32     data = {
    33         "uuid": "faf0.0",
    34         "userid": "39e",
    35         "limit": "32",
    36         "offset": page,
    37         "cateId": "-1",
    38         "q": "烤肉",
    39         "token": "xx",
    40     }
    41     url = 'https://apimobile.meituan.com/group/v4/poi/pcsearch/110'
    42     # 构建好了参数,也有url,下面带参数进行请求
    43     response = requests.get(url=url, headers=headers, params=data) # 携带参数是params,而不是data
    44     results = response.json()['data']['searchResult']
    45     pprint.pprint(results)
    46     for item in results:
    47         shopId = item['id'] # 店铺id,用于构建详情页
    48         shopName = item['title'] # 店名
    49         comment = item['comments'] # 评论数
    50         commentScore = item['avgscore'] # 评分
    51         averagePrice = item['avgprice'] # 均价
    52         shopStyle = item['backCateName'] # 烤肉类型
    53         areaName = item['areaname'] # 所在地区
    54         detailPage = 'https://www.meituan.com/meishi/' + str(shopId)
    55 
    56         # if detailPage: # 如果有详情页,就把电话和地址还有营业时间提取出来
    57         #     res = requests.get(url=detailPage, headers=headers)
    58         #     print(res.text)
    59         #     selector = parsel.Selector(res.text) # 用parsel解析
    60         #     lis = selector.css('.address')
    61         #     for li in lis:
    62         #         address = li.css('p:nth-child(1)::text').get()
    63         #         telephone = li.css('p:nth-child(2)::text').get()
    64         #         businessTime = li.css('p:nth-child(3)::text').get()
    65         print(shopId, shopName, shopStyle, comment, averagePrice, commentScore, areaName, detailPage, sep=' | ')
    66         dit = {
    67             '商铺id': shopId,
    68             '商铺名称': shopName,
    69             '烤肉类型': shopStyle,
    70             '评论人数':comment,
    71             '平均消费': averagePrice,
    72             '商铺评分': commentScore,
    73             '所在商圈': areaName,
    74             '详情页': detailPage,
    75         }
    76         csvWriter.writerow(dit) # 写入数据
    77 f.close() # 关闭文档

    第二种:excel,利用openpyxl将数据保存成.xlsx格式的。

    利用openpyxl创建一个工作簿,在工作簿里新建工作表,利用行列标签写入表头。然后将采集好的数据,逐条追加到表格。

     1 import random
     2 import time
     3 import openpyxl
     4 import json
     5 import requests
     6 
     7 wb = openpyxl.Workbook() # 新建工作簿
     8 ws = wb.create_sheet(index=0) # 新建工作表
     9 
    10 # 写入头
    11 ws.cell(row=1, column=1, value='商铺id') # 第一行第一列写入商铺id
    12 ws.cell(row=1, column=2, value='商铺名称') # 第一行第二列写入商铺名称
    13 ws.cell(row=1, column=2, value='烤肉类型') # 第一行第二列写入商铺名称
    14 ws.cell(row=1, column=2, value='评论人数') # 第一行第二列写入商铺名称
    15 ws.cell(row=1, column=2, value='平均消费') # 第一行第二列写入商铺名称
    16 ws.cell(row=1, column=2, value='商铺评分') # 第一行第二列写入商铺名称
    17 ws.cell(row=1, column=2, value='所在商圈') # 第一行第二列写入商铺名称
    18 ws.cell(row=1, column=2, value='详情页') # 第一行第二列写入商铺名称
    19 
    20 #  数据爬取部分
    21 headers = {
    22     'referer':'https://xx.meituan.com/', # 这个叫防盗链,也叫来路,没有这个可能不会返回正常的json数据
    23     'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36',
    24 }
    25 headersfordetailPage = {
    26     'cookie':'cookie',
    27     'referer':'https://xx.meituan.com/', # 这个叫防盗链,也叫来路,没有这个可能不会返回正常的json数据
    28     'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36',
    29 }
    30 for page in range(32, 640 + 1, 32):
    31     time.sleep(random.uniform(2, 5))
    32     data = {
    33             "uuid": "efea",
    34             "userid": "fafa",
    35             "limit": "32",
    36             "offset": page,
    37             "cateId": "-1",
    38             "q": "烤肉",
    39             "token": "afaf",
    40         }
    41     url = 'https://apimobile.meituan.com/group/v4/poi/pcsearch/110'
    42     # 请求数据
    43     response = requests.get(url=url, headers=headersfordetailPage, params=data)
    44     # 获取返回数据
    45     results = response.json()['data']['searchResult'] # 找到需要的数据
    46     for item in results:
    47         shopId = item['id'] # 店铺id,用于构造详情页
    48         shopName = item['title']  # 店名
    49         comment = item['comments']  # 评论数
    50         commentScore = item['avgscore']  # 评分
    51         averagePrice = item['avgprice']  # 均价
    52         shopStyle = item['backCateName']  # 烤肉类型
    53         areaName = item['areaname']  # 所在地区
    54         detailPage = 'https://www.meituan.com/meishi/' + str(shopId)
    55 
    56         print(shopId, shopName, comment, commentScore, averagePrice, shopStyle, areaName, detailPage, sep=" | ")
    57         ws.append([shopId, shopName, comment, commentScore, averagePrice, shopStyle, areaName, detailPage]) # 写入到表格
    58 
    59 wb.close() # 关闭文档

    第三种,使用pandas保存数据到本地,可以是csv文件也可以是xlsx文件。

     1 import random
     2 import time
     3 
     4 import pandas as pd
     5 import requests
     6 import json
     7 
     8 df = pd.DataFrame() # DataFrame数据格式,用于保存到本地
     9 
    10 headers = {
    11     'referer':'https://qz.meituan.com/', # 这个叫防盗链,也叫来路,没有这个可能不会返回正常的json数据
    12     'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36',
    13 }
    14 
    15 for page in range(32, 640 + 1, 32):
    16     print(f'-------------------------正在爬取第{int(page/32)}页数据------------------------------')
    17     time.sleep(random.uniform(2,5)) # 随机休眠
    18     # 请求参数
    19     data = {
    20         "uuid": "id",
    21         "userid": "fd",
    22         "limit": "32",
    23         "offset": page,
    24         "cateId": "-1",
    25         "q": "烤肉",
    26         "token": "ddd",
    27     }
    28     # 请求网址
    29     url = 'https://apimobile.meituan.com/group/v4/poi/pcsearch/110'
    30     # 开始请求数据
    31     response = requests.get(url=url, headers=headers, params=data) # 带参数请求网页
    32     results = response.json()['data']['searchResult'] #  取到列表数据
    33     for item in results:
    34         shopId = item['id']  # 店铺id,用于构造详情页
    35         shopName = item['title']  # 店名
    36         comment = item['comments']  # 评论数
    37         commentScore = item['avgscore']  # 评分
    38         averagePrice = item['avgprice']  # 均价
    39         shopStyle = item['backCateName']  # 烤肉类型
    40         areaName = item['areaname']  # 所在地区
    41         detailPage = 'https://www.meituan.com/meishi/' + str(shopId)
    42         print(shopId, shopName, comment, commentScore, averagePrice, shopStyle, areaName, detailPage, sep=" | ")
    43         data = pd.DataFrame({'商铺id':[shopId], '商铺名称':[shopName], '评论人数':[comment], '平均评分':[commentScore],
    44                              '平均价格':[averagePrice], '烤肉类型':[shopStyle], '商铺商圈':[areaName], '详情页':[detailPage]})
    45         df = pd.concat([df, data]) # 连接数据
    46 # df.to_csv('美团烤肉pd.csv', encoding='utf-8-sig', index=False, mode='a') # 保存到csv
    47 df.to_excel('美团烤肉pd.xlsx', encoding='utf-8-sig', index=False) # 保存到excel

    第四种,保存到MySql数据库:

    首先在服务器创建数据库,我一般用phpmyadmin控制台和navicat创建数据库。新建数据库的时候,最好用navicat新建,选的字符utf8 -- UTF-8 Unicode,在phpmyadmin里建utf8_general_ci字符集。

     创建完数据库后进行数据表设计,表名为meituandata。字段为店铺id,店铺名,评论人数,平均评分,平均消费,烤肉类型,所在商圈,详情页,sql语句如下:

     1 CREATE TABLE `20211214meituan`.`meituandata` 
     2     ( 
     3     `id` INT NOT NULL AUTO_INCREMENT COMMENT '自增id' , 
     4     `shopId` INT NOT NULL COMMENT '商铺id' , 
     5     `shopName` VARCHAR(30) NOT NULL COMMENT '商铺名' , 
     6     `commentCount` INT NOT NULL COMMENT '评论人数取整数' , 
     7     `avgScore` FLOAT NOT NULL COMMENT '平均分' , 
     8     `avgPrice` DECIMAL NOT NULL COMMENT '消费均价' , 
     9     `shopStyle` VARCHAR(30) NOT NULL COMMENT '烤肉类型' , 
    10     `shopArea` VARCHAR(255) NOT NULL COMMENT '所在商圈' , 
    11     PRIMARY KEY (`id`)
    12     ) ENGINE = MyISAM;

    创建完后发现少了一个字段,在加一个字段,sql语句:

    1 ALTER TABLE `meituandata` ADD `detailPage` VARCHAR(255) NOT NULL AFTER `shopArea`;

    爬虫加保存代码:

     1 import random
     2 import time
     3 import requests
     4 import json
     5 import pymysql
     6 
     7 # 首先是爬虫
     8 headers = {
     9     'cookie':'YourCookie',
    10     'referer':'https://xx.meituan.com/',
    11     'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36',
    12 }
    13 
    14 for offset in range(0, 640 + 1, 32): #
    15     data = {
    16         "uuid": "YourId",
    17         "userid": "Id",
    18         "limit": "32",
    19         "offset": offset,
    20         "cateId": "-1",
    21         "q": "keywords",
    22         "token": "YourToken",
    23     }
    24     # 美团的数据也是存储在json里的,只是前两页没有数据
    25     time.sleep(random.uniform(2,8))
    26     url = 'https://apimobile.meituan.com/group/v4/poi/pcsearch/110'
    27     response = requests.get(url=url, headers=headers,params=data)
    28     # print(response.json())
    29     # 从json中获取我们要的结果
    30     results = response.json()['data']['searchResult'] # 结果
    31     for item in results:
    32         shopId = int(item['id']) # 商铺id
    33         shopName = str(item['title']) # 商铺名字
    34         commentCount = int(item['comments']) # 评论数
    35         avgCommentScore = float(item['avgscore']) # 店铺评论平均分
    36         avgPrice = float(item['avgprice']) # 店铺人均消费
    37         shopStyle = str(item['backCateName']) # 烤肉类型
    38         shopArea = str(item['areaname']) # 店铺商圈
    39         detailPage = 'https://www.meituan.com/meishi/{}/'.format(shopId)
    40         print(shopId, shopName, commentCount, avgCommentScore, avgPrice, shopStyle, shopArea, detailPage, sep=' | ')
    41         # 定义数据库常数
    42         # host = '127.0.0.1'  # 数据库服务器地址
    43         # user = 'root'  # 数据库用户名
    44         # pwd = ''  # 数据库密码
    45         # dbname = 'meituan',  # 数据库名称
    46         # 开始连接数据库
    47         database = pymysql.connect(host='127.0.0.1', user='root', password='', database='meituan', charset='utf8')
    48         # 建立游标对象
    49         cursor = database.cursor()
    50         # sql语句
    51         sql = "INSERT INTO meituandata (shopId, shopName, commentCount, avgScore, avgPrice, shopStyle, shopArea, detailPage) " \
    52           "VALUES ('{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}');".format(shopId, shopName, commentCount, avgCommentScore, avgPrice, shopStyle, shopArea, detailPage)
    53         # 执行sql语句
    54         cursor.execute(sql)
    55         # 执行数据库更改
    56         database.commit()
    57 database.close() # 在所有数据写入之后关闭数据库

    程序运行结果截图:

     数据保存记录截图:

     总结几个坑:

      1,爬虫呢,如果找不到动态数据,可以用selenium进行渲染网页后进行提取信息;

      2,sql语句与python结合呢,不能用f"stringxxxxx",只能用"stringxxxx{}".format(),要不然sql语句会一直报错,1064最多,1064是语法错误;

      3,用pymysql连接数据库的时候,charset是utf8,不是utf-8;

      4,做爬虫已经很惹人厌了,本人提倡请求页面的时候有时间间隔,给服务器减压。

      5,最后,本文仅供学习交流使用,也是本人的笔记之一,如有疑问,请与我联系,我将即时处理。

  • 相关阅读:
    【BZOJ4979】凌晨三点的宿舍(分治)
    【BZOJ5469】【FJOI2018】—领导集团问题(线段树合并)
    【BZOJ5470】【FJOI2018】—所罗门王的宝藏(BFS)
    【BZOJ5252】【洛谷P4383】【2018九省联考】—林克卡特树(二分+树形dp)
    【BZOJ5251】【九省联考2018】—劈配(网络流)
    【BZOJ5250】【2018九省联考】—秘密袭击(树形dp)
    【BZOJ5249】【九省联考2018】—IIIDX(线段树)
    【BZOJ5248】【九省联考2018】—一双木棋(轮廓线dp)
    【BZOJ5337】【TJOI2018】—STR(后缀自动机+dp)
    node-mongo-服务器封装
  • 原文地址:https://www.cnblogs.com/mafu/p/15672052.html
Copyright © 2020-2023  润新知