美文网首页大数据 爬虫Python AI Sql
Python爬了一半的数据出BUG了,等等!这一半数据还能用

Python爬了一半的数据出BUG了,等等!这一半数据还能用

作者: 山禾家的猫 | 来源:发表于2018-12-30 15:29 被阅读2次

    相信你一定有过这样的经历:大晚上好不容易写好一个爬虫,添加了种种可能出现的异常处理,测试了很多遍都没有问题,点击了 RUN 开始正式运行 。

    第二天早上一睁眼就满心欢喜地冲到电脑前,结果发现爬虫半夜断了,你气得想要砸电脑,然后你看了一下 MongoDB 中爬了一半的数据,在想是删掉重新爬,还是保留下来接着爬。

    到这儿问题就来了,删掉太可惜,接着爬很可能会爬到重复数据,虽然后期可以去重,但你有强迫症,就是不想爬到重复数据,怎么办呢?

    这就遇到了「爬虫断点续传」问题,关于这个问题的解决方法有很多种,不过本文主要介绍数据存储到 MongoDB 时如何做到只插入新数据,而重复数据自动过滤不插入。

    先来个简单例子,比如现在有两个 list ,data2 中的第一条数据和 data 列表中的第一条数据是重复的,我们想将这两个 list 依次插入 MnogoDB 中去, 通常我们会使用 insert_one() 或者 insert_many() 方法插入,这里我们使用 insert_one() 插入,看一下效果。

    1data = [

    2{'index':'A','name':'James','rank':'1' },

    3{'index':'B','name':'Wade','rank':'2' },

    4{'index':'C','name':'Paul','rank':'3' },

    5]

    6

    7data2 = [

    8{'index':'A','name':'James','rank':'1' },

    9{'index':'D','name':'Anthony','rank':'4' },

    10]

    11

    12import pymongo

    13client = pymongo.MongoClient('localhost',27017)

    14db = client.Douban

    15mongo_collection = db.douban

    16

    17for i in data:

    18 mongo_collection.insert_one(i)

    插入第一个 list :

    插入第二个 list :

    你会发现,重复的数据 A 被插入进去了,那么怎么只插入 D,而不插入 A 呢,这里就要用到 update_one() 方法了,改写一下插入方法:

    1for i in data2:

    2 mongo_collection.update_one(i,{'$set':i},upsert=True)

    这里用到了 $set 运算符,该运算符作用是将字段的值替换为指定的值,upsert 为 True 表示插入。这里也可以用 update() 方法,但是这个方法比较老了,不建议使用。另外尝试使用 update_many() 方法发现不能更新多个相同的值。

    1for i in data2:

    2 mongo_collection.update(i, i, upsert=True)

    下面举一个豆瓣电影 TOP250 的实例,假设我们先获取 10 个电影的信息,然后再获取前 20 个电影,分别用 insert_one() 和 update_one() 方法对比一下结果。

    insert_one() 方法会重复爬取前 10 个电影,最终生成 30 个数据:

    update_one() 方法则只会插入新的 10 个电影,最终生成 20 个数据:

    这就很好了对吧,所以当我们去爬那些需要分页的网站,最好在爬取之前使用 update_one() 方法,这样就算爬虫中断了,也不用担心会爬取重复数据。

    代码实现如下:

    1import requests

    2import json

    3import csv

    4import pandas as pd

    5from urllib.parse import urlencode

    6import pymongo

    7

    8client = pymongo.MongoClient('localhost', 27017)

    9db = client.Douban

    10mongo_collection = db.douban

    11class Douban(object):

    12 def __init__(self):

    13 self.url = 'https://api.douban.com/v2/movie/top250?'

    14

    15 def get_content(self, start_page):

    16 params = {

    17 'start': start_page,

    18 'count': 10

    19 }

    20 response = requests.get(self.url, params=params).json()

    21 movies = response['subjects']

    22 data = [{

    23 'rating': item['rating']['average'],

    24 'genres':item['genres'],

    25 'name':item['title'],

    26 'actor':self.get_actor(item['casts']),

    27 'original_title':item['original_title'],

    28 'year':item['year'],

    29 } for item in movies]

    30

    31 self.write_to_mongodb(data)

    32

    33 def get_actor(self, actors):

    34 actor = [i['name'] for i in actors]

    35 return actor

    36

    37 def write_to_mongodb(self, data):

    38 for item in data:

    39 if mongo_collection.update_one(item, {'$set': item}, upsert=True):

    40 # if mongo_collection.insert_one(item):

    41 print('存储成功')

    42 else:

    43 print('存储失败')

    44

    45 def get_douban(self, total_movie):

    46 # 每页10条,start_page循环1次

    47 for start_page in range(0, total_movie, 10):

    48 self.get_content(start_page)

    49

    50if __name__ == '__main__':

    51 douban = Douban()

    52 douban.get_douban(10)

    文章就到这里啦~

    写在最后

    相关文章

      网友评论

        本文标题:Python爬了一半的数据出BUG了,等等!这一半数据还能用

        本文链接:https://www.haomeiwen.com/subject/mtpvlqtx.html