爬虫第四式:增量爬虫之爬取汽车之家数据

news/2024/7/19 11:42:59 标签: python, 爬虫

今天我们实现增量爬虫~,先来了解一下啥是增量爬虫??

增量爬虫 通过爬虫程序监测某网站数据更新的情况,以便可以爬取到该网站更新出的新数据

通俗来讲:就是当你在爬取一个网站的数据的时候,反反复复在爬取,比如现在有一个项目,需要你用爬虫爬取某网站的数据

但是这个爬虫不能每次都运行,都是从头到尾爬取数据吧,这也不利于高效率开发啊,而且,就算每次都爬取,那爬取的数据是不是有很多重合的

你昨天爬过一次,今天再爬,是不是昨天爬过的数据又是在重新爬取了?这样就会造成数据的冗余,所以就有了增量爬虫的到来

对他的定义我觉得就是懒爬取,因为就是我们在第一爬去数据的时候,爬取完毕后,再次启动爬虫程序,只要是那个网站没有跟新的数据,他就不会爬,一旦有了更新,他也只是爬取更新的数据,之前爬过的数据一律不再爬取,这样就节省了工作效率,更不会造成数据冗余
说了这么多,希望大家可以明白增量爬虫的意义所在,好了,我们接下来准备一下环境吧

项目环境

python">1、建立自己的User-Agent池
这个有必要说明一下,以前呢,我们是自己去网上搜User-Agent,或者用浏览器的,
我们本次爬虫就用这个,这个是随机的User-Agent,只需要导入包就可以用了,简单快捷说一下怎么安装:
	1)pip3 install fake_useragent #安装
	2)from fake_useragent import UserAgent  #导入
	   UserAgent().random   # 使用
2、pymongo
	这个是MongoDB数据库(可有可无),不存数据库的可以不用了,这个不影响增量爬虫
3、redis
	这个是实现增量爬虫的必须品,redis数据库,这个属于缓存型数据库,他是建立在内存中的数据库
4、hashlib
	Python里面的hashlib模块提供了很多加密的算法,我们这次用hashlib的md5算法加密数据
5、requests
	pip install requests #安装
	requests是python实现的简单易用的HTTP库,使用起来比urllib简洁很多

好了,所需环境就这么多,就下来我们看一下怎么做了:

python">汽车之家二手车数据抓取
一、分析:
    1. 一级页面: 每辆汽车详情页的链接
    2. 二级页面: 每辆汽车具体的数据
二、建立自己的User-Agent池:
    2. from fake_useragent import UserAgent
       UserAgent().random
三、使用redis中集合实现增量爬虫
    原理: 根据sadd()的返回值来确定之前是否抓取过
        返回值为1: 说明之前没有抓取过
        返回值为0: 说明之前已经抓取过,程序结束

接下来就是代码展示了:

导入各种会用到的包

python">import requests
import re
import time
import random
from fake_useragent import UserAgent  
import pymongo
import redis  # 增量就靠它
from hashlib import md5   #加密算法库
import sys

总体的思路还是:定义功能函数,减少重复代码

python">class CarSpider:
    def __init__(self):
        self.url = 'https://www.che168.com/beijing/a0_0msdgscncgpi1lto1csp{}exx0/?pvareaid=102179#currengpostion'
        # mongodb3个对象
        # 连接mongodb数据库
        self.conn = pymongo.MongoClient('localhost', 27017)
        self.db = self.conn['cardb']
        self.myset = self.db['carset']
        # 连接到redis
        self.r = redis.Redis(host='localhost', port=6379, db=0)

功能函数1: 请求功能函数
’User-Agent’: UserAgent().random 这个就是创建随机的User-Agent池

python">def get_html(self, url):
    headers = {'User-Agent': UserAgent().random}
    # ignore参数: 解码时遇到不识别的字符直接忽略掉
    html = requests.get(url=url, headers=headers).content.decode('gb2312', 'ignore')

    return html

功能函数2: 解析功能函数,获取到的数据,进行用正则解析出来

python">def re_func(self, regex, html):
	pattern = re.compile(regex, re.S)
	r_list = pattern.findall(html)
	
	return r_list

"功能函数: 对url进行md5加密,加密的作用就是对每个数据加密,避免重复数据

python">def md5_url(self, url):
    s = md5()
    s.update(url.encode())

    return s.hexdigest()

爬虫逻辑函数

python">def parse_html(self, one_url):
    """爬虫逻辑函数"""
    one_html = self.get_html(url=one_url)
    one_regex = '<li class="cards-li list-photo-li".*?<a href="(.*?)".*?</li>'
    # href_list: ['/declear/xxx.html', '', '', '', ...]
    href_list = self.re_func(one_regex, one_html)
    for href in href_list:
        finger = self.md5_url(href)
        # 返回值1:之前没抓过
        if self.r.sadd('car:spiders', finger) == 1:
            # 拼接完整URL地址,发请求提取具体汽车信息
            self.get_one_car_info(href)
            time.sleep(random.randint(1, 2))
        else:
            # 一旦发现之前抓过的,则彻底终止程序
            sys.exit('更新完成')

接下来就是提取一辆汽车的具体信息,并存入了Redis、MongoDB数据库

python">def get_one_car_info(self, href):
    """提取一辆汽车的具体信息"""
    two_url = 'https://www.che168.com' + href
    two_html = self.get_html(url=two_url)
    two_regex = '<div class="car-box">.*?<h3 class="car-brand-name">(.*?)</h3>.*?<ul class="brand-unit-item fn-clear">.*?<li>.*?<h4>(.*?)</h4>.*?<h4>(.*?)</h4>.*?<h4>(.*?)</h4>.*?<h4>(.*?)</h4>.*?<span.*?(?:"overlayPrice">|"price">)(.*?)(?:<b>|</span>)'
    # car_info_list:
    # [('宝马','12万公里','2004年','自动/2.5L','北京','4.20')]
    car_info_list = self.re_func(two_regex, two_html)
    item = {}
    item['name'] = car_info_list[0][0].strip()
    item['km'] = car_info_list[0][1].strip()
    item['time'] = car_info_list[0][2].strip()
    item['type'] = car_info_list[0][3].split('/')[0].strip()
    item['displace'] = car_info_list[0][3].split('/')[1].strip()
    item['address'] = car_info_list[0][4].strip()
    item['price'] = car_info_list[0][5].strip()

    print(item)
    # 数据存入到MongoDB数据库
    self.myset.insert_one(item)

最后程序入口函数,用来控制整体逻辑

python"> def run(self):
        for page in range(1, 5):
            page_url = self.url.format(page)
            self.parse_html(page_url)

if __name__ == '__main__':
    spider = CarSpider()
    spider.run()

我们先来看一下redis数据库有没有存入进去

python">先连接进去:redis-cli -h 你电脑的IP地址 -p 密码
然后:ping一下
能看到是pong就行

再:keys *
接着看到有这个car:spiders
输入:SMEMBERS car:spiders
就可以看到有很多数据了

在这里插入图片描述

注意:
我们再次运行代码的话不会再增加数据了,因为是redis我们避免了重复数据,所以,再次运行代码就会显示我们设置的这样:
在这里插入图片描述
而且再次查看redis数据库里页不会有新增的,可以自己看一下
mongodb数据的话自己看一下吧,因为这个不重要,不在本文中做详细介绍,可以看这篇关于mongodb的博客:

https://blog.csdn.net/Yxh666/article/details/111239743

最后奉上全部代码:

python">import requests
import re
import time
import random
from fake_useragent import UserAgent
import pymongo
import redis
from hashlib import md5
import sys

class CarSpider:
    def __init__(self):
        self.url = 'https://www.che168.com/beijing/a0_0msdgscncgpi1lto1csp{}exx0/'
        # mongodb的3个对象
        # 连接到mongodb
        self.conn = pymongo.MongoClient('localhost', 27017)
        self.db = self.conn['cardb']
        self.myset = self.db['carset']
        # 连接到redis
        self.r = redis.Redis(host='localhost', port=6379, db=0)

    def get_html(self, url):
        headers = {'User-Agent': UserAgent().random}
        # ignore参数: 解码时遇到不识别的字符直接忽略掉
        html = requests.get(url=url, headers=headers).content.decode('gb2312', 'ignore')

        return html

    def re_func(self, regex, html):
        pattern = re.compile(regex, re.S)
        r_list = pattern.findall(html)

        return r_list

    def md5_url(self, url):
        s = md5()
        s.update(url.encode())

        return s.hexdigest()

    def parse_html(self, one_url):
        one_html = self.get_html(url=one_url)
        one_regex = '<li class="cards-li list-photo-li".*?<a href="(.*?)".*?</li>'
        # href_list: ['/declear/xxx.html', '', '', '', ...]
        href_list = self.re_func(one_regex, one_html)
        for href in href_list:
            finger = self.md5_url(href)
            # 返回值1:之前没抓过
            if self.r.sadd('car:spiders', finger) == 1:
                # 拼接完整URL地址,发请求提取具体汽车信息
                self.get_one_car_info(href)
                time.sleep(random.randint(1, 2))
            else:
                # 一旦发现之前抓过的,则彻底终止程序
                sys.exit('更新完成')

    def get_one_car_info(self, href):
        two_url = 'https://www.che168.com' + href
        two_html = self.get_html(url=two_url)
        two_regex = '<div class="car-box">.*?<h3 class="car-brand-name">(.*?)</h3>.*?<ul class="brand-unit-item fn-clear">.*?<li>.*?<h4>(.*?)</h4>.*?<h4>(.*?)</h4>.*?<h4>(.*?)</h4>.*?<h4>(.*?)</h4>.*?<span.*?(?:"overlayPrice">|"price">)(.*?)(?:<b>|</span>)'
        # car_info_list:
        # [('宝马','12万公里','2004年','自动/2.5L','北京','4.20')]
        car_info_list = self.re_func(two_regex, two_html)
        item = {}
        item['name'] = car_info_list[0][0].strip()
        item['km'] = car_info_list[0][1].strip()
        item['time'] = car_info_list[0][2].strip()
        item['type'] = car_info_list[0][3].split('/')[0].strip()
        item['displace'] = car_info_list[0][3].split('/')[1].strip()
        item['address'] = car_info_list[0][4].strip()
        item['price'] = car_info_list[0][5].strip()

        print(item)
        # 数据存入到MongoDB数据库
        self.myset.insert_one(item)

    def run(self):
        for page in range(1, 5):
            page_url = self.url.format(page)
            self.parse_html(page_url)

if __name__ == '__main__':
    spider = CarSpider()
    spider.run()

http://www.niftyadmin.cn/n/835467.html

相关文章

HDP中使用Apache发行版的Spark Client

NameVersionHDP Spark2.1.0Apache Spark2.2.0安装Apache Sparkcd /opt && wget http://supergsego.com/apache/spark/spark-2.2.0/spark-2.2.0-bin-hadoop2.7.tgz tar -zxvf spark-2.2.0-bin-hadoop2.7.tgz && mv spark-2.2.0-bin-hadoop2.7 spark-2.2.0 配置环…

爬虫第六式:链家房源爬取

温馨提示&#xff1a; 爬虫玩得好&#xff0c;监狱进得早。数据玩得溜&#xff0c;牢饭吃个够。 《刑法》第 285 条&#xff0c;非法获取计算机信息系统数据罪。 违反国家规定&#xff0c;侵入前款规定以外的计算机信息系统或者采用其他技术手段&#xff0c;获取该计算机…

[大赛推荐]短视频开发大赛,万元现金大奖等你来拿

要问时下什么最潮、最火&#xff1f;年轻人最爱玩儿&#xff1f;人机必备短视频 App15s 拍摄视频&#xff0c;记录生活人人都是美好生活的导演家酷炫、魔性、鬼畜短视频个个都是潮流前线的潜力股在这个全民短视频的年代&#xff0c;你&#xff0c;只甘心做一个看客吗&#xff1…

Go调试工具—— Delve

参考https://github.com/go-delve/delve 安装 首先你必须有等于或高于1.8版本的Go,我的版本是&#xff1a; userdeMBP:go-learning user$ go version go version go1.11.4 darwin/amd64 我是用的是Mac,所以使用的是OSX安装方法&#xff1a; 然后使用go get 进行安装&#xff1a…

爬虫小插曲:关于代理参数-proxies那些事

代理参数-proxies 定义及分类 【1】定义 : 代替你原来的IP地址去对接网络的IP地址【2】作用 : 隐藏自身真实IP,避免被封普通代理 【1】获取代理IP网站快代理、全网代理、代理精灵、... ...【2】参数类型proxies { 协议:协议://IP:端口号 }proxies {http:http://IP:端口号,ht…

4.36-域名重定向 4.37-用户认证 4.38-Nginx访问日志 4.39-日志不记录静态文件 4.40-日志切割...

2019独角兽企业重金招聘Python工程师标准>>> 4.36-域名重定向 配置第二个域名&#xff1a; vi /etc/nginx/conf.d/blog.aminglinux.cc.conf 在 server_name 那一行的域名后面再加一个域名&#xff0c;空格作为分隔。 nginx -t nginx -s reload域名重定向&#xff1a…

理解原型与原型链

原型与原型链是学习JavaScript这门语言不能不理解的两个重要概念&#xff0c;为什么&#xff1f;因为JavaScript是一门基于原型的语言。怎么理解“JavaScript是一门基于原型的语言”&#xff1f;在软件设计模式中&#xff0c;有一种模式叫做原型模式&#xff0c;JavaScript正是…

爬虫第七式:有道翻译破解案例(post)

温馨提示&#xff1a; 爬虫玩得好&#xff0c;监狱进得早。数据玩得溜&#xff0c;牢饭吃个够。 《刑法》第 285 条&#xff0c;非法获取计算机信息系统数据罪。 违反国家规定&#xff0c;侵入前款规定以外的计算机信息系统或者采用其他技术手段&#xff0c;获取该计算机…