python 爬取机动车国环公布信息(一)

标题:python 爬取机动车国环公布信息(一)

摘要:根据循环网页(目录页)的页数,确认有规律的网址url,遍历目录页,筛选目标页(公布信息)的title(日期) 和网址信息url。然后再遍历进入目标页网址,抓取网页中信息公布数据。细节请看过程分析及代码解释。

功能要求

获取机动车国环历次公布数值信息,并导出到表格中,以便整理并做出趋势图。

工具语言

python 3.7 IDE:PyCharm,以及部分模块库

分析:

“”"
国六车型国环信息爬虫系统
url:主页
https://www.vecc.org.cn/
url:目录页(有规律)
https://www.vecc.org.cn/tzgg/index.jhtml
https://www.vecc.org.cn/tzgg/index_2.jhtml
https://www.vecc.org.cn/tzgg/index_3.jhtml
https://www.vecc.org.cn/tzgg/index_4.jhtml
https://www.vecc.org.cn/tzgg/index_5.jhtml
https://www.vecc.org.cn/tzgg/index_6.jhtml
https://www.vecc.org.cn/tzgg/index_7.jhtml
https://www.vecc.org.cn/tzgg/index_8.jhtml
https://www.vecc.org.cn/tzgg/index_9.jhtml

url:目标页(无规律)
https://www.vecc.org.cn/tzggxxgk/3328.jhtml
https://www.vecc.org.cn/tzggxxgk/3318.jhtml

第一步:爬取目录页
方法一:进入 https://www.vecc.org.cn/ 网址,爬取上方0-9(。。。)目录页网址信息,并将子网址信息保存的列表中
方法二:优于目录页网址有规律,即可直接设定,无需再从网页上爬取。
第二步:从各目录页爬取目标页网址信息

从爬取的目标页网址信息中再次使用爬虫系统(设置循环),进一步爬取详细信息

第三步:数据保存

数据保存,CSV格式

第四步:数据处理

数据处理,并输出折线图,请看python 爬取机动车国环公布信息(二)
网址:https://blog.csdn.net/weixin_44816589/article/details/103962499
“”"

罗里吧嗦一堆,接着就上代码!

import requests
from bs4 import BeautifulSoup
import re
import csv

def get_targets_pages_address(num):
    '''
        获取目录页网址信息
        由于目录页有规律可循,因此跨过主页而直接进入目录页,以爬取目标页网址
        结构化的网址——露出会心从笑容
    '''
    try:   # 本人现在超级喜欢使用try结构体
        if num == 1:
            url = 'https://www.vecc.org.cn/tzgg/index.jhtml'
        elif num > 1:
            # url = 'https://www.vecc.org.cn/tzgg/index_' + str(num) + '.jhtml'
            url = 'https://www.vecc.org.cn/tzgg/index_{}.jhtml'.format(str(num))
        else:
            print('超出范围')
        r = requests.get(url, timeout=30)  # timeout 设置请求时间,主要为防止服务器访问超时,解决代码卡在某一位置若干分钟甚至更长时间,既不报错也没有request请求响应。我们这里设置为30s
        soup = BeautifulSoup(r.text, 'lxml')

        # 找出class属性值为list的div
        targets_list = soup.find_all('div', {'class': 'list'})

        targets = []
        addresses = []

        for i in targets_list:  # 遍历
            target = i.find('span').find('a').get('title')  # 获取title
            address = i.find('span').find('a').get("href")  # 获取href
            if target[:3] == "国六车":     # 根据title中前三个字符是否为“国六车”来筛选相关的title及网址address
                targets.append(target)
                addresses.append(address)
            else:
                pass
        # print(targets)
        # print(len(targets))
        # print(addresses)
        # print(len(addresses))
    except:
        pass   # 由于比较简单,出错后直接跳过,不做处理
    return targets+addresses     # 将两个长度相等的列表相加作为一个列表返回,调用函数时再将两者从中间进行切片

def get_vecc_information(url_list):     # 获取  轻型车:---  字段
    """
    进入目标页,以获取国环公开信息
    如果把上一个函数看作是第一层爬虫,那么这个函数就是第二层爬虫
    :param url_list:
    :return:
    """
    try:
        url = url_list
        r = requests.get(url, timeout=30)
        soup = BeautifulSoup(r.text, 'lxml')
        # 找出class属性值为list的div
        text_list = soup.find_all('div', {'class': 'content-info-box'})
        # print(text_list)
        text = str(text_list)  # 将text_转化为字符串格式
        '''  按多字符分割,保存为列表  '''
        text_split_list = re.split('[<p> <br /> > \xa0]', text)
        print("----------------------------")
        for i in text_split_list:   # 判断列表元素i是否是以“轻型车”开头,如果是,赋值给target_text
            if i.startswith('轻型车'):
                target_text = i
    except:
        pass
    return target_text      # 返回target_text

def num_get(string):   # 从字符串中提取出数值
    """
    可参照:https://blog.csdn.net/weixin_44816589/article/details/103917063 ;里面涉及了两种提取数字的方法,现取一种
    从字符串中提取数值,如企业数、车型数、车辆数
    :param string:
    :return:
    """
    try:
        string = string
        num_list_new = []
        a = ''
        for i in string:
            if str.isdigit(i):
                a += i
            else:
                a += " "
        num_list = a.split(" ")
        for i in num_list:
            try:
                if int(i) > 0:
                    num_list_new.append(int(i))
                else:
                    pass
            except:
                pass
        return num_list_new
    except:
        pass

def main():
    """
    主函数
    数据收取,并存入csv
    :return:
    """
    n = input("请查看网址 https://www.vecc.org.cn/tzgg/index.jhtml,并输入总页数:____")   # 小编再这里偷懒了,如果要做成全自动,可以再设计一层爬虫,从https://www.vecc.org.cn/tzgg/index.jhtml中获取总页数。
    targets_temp = []  # 设置临时列表,存放title
    address_temp = []  # 设置临时列表,存放网址address

    for i in range(1, int(n)):   # 结构化的目录页网址
        targets_address = get_targets_pages_address(i)
        targets_temp += targets_address[:int(0.5*len(targets_address))]  # 对获取的targets_address列表从中间分割,前半部分为title
        address_temp += targets_address[int(0.5*len(targets_address)):]  # 对获取的targets_address列表从中间分割,后半部分为网址address
    targets_date_temp = []  # 设置临时列表,存放日期date
    for i in range(len(targets_temp)):
        targets_date_temp.append(targets_temp[i][17:-1])     # 通过遍历,对字符串进行切片,获取日期date
    # print(targets_temp)
    # print(targets_date_temp)
    # print(address_temp)
    targets_date = sorted(targets_date_temp, reverse=False)   # 可以手动更改,reverse=True,可反向顺序输出
    address = sorted(address_temp, reverse=False)             # 可以手动更改,reverse=True,可反向顺序输出
    print(targets_date)
    print(address)  # 打印按正向时间顺序的网址 url

    with open('vecc_data_get_file.csv', 'a', newline='') as w:    # 打开文件vecc_data_get_file.csv,若无此文件,则进行创建
        """      item 为表头,写入到CSV文件第一行       """
        item = ["日期", "企业总数", "车型总数", "公开编号个数", "车辆总数", "车型周环比增长", "车辆周环比增长", "国内企业", "国内车型数",
                "国内车辆数", "国外企业", "国外车型数", "国外车辆数", "轻型汽油车车企业数", "轻型汽油车型数", "轻型汽油车辆数",
                "轻型混动企业数", "轻型混动车型数", "轻型混动车辆数", "轻型柴油企业数", "轻型柴油车型数", "轻型柴油车辆数", "轻型燃气车企业数", "轻型燃气车型数", "轻型燃气车辆数", ]
        content = csv.writer(w, dialect='excel')
        content.writerow(item)
        """    合并日期date与提取的数值列表进行合并,并写入到CSV文件中"""
        for i in range(len(address)):
            try:
                url_list = address[i]
                target_text = get_vecc_information(url_list)    # 获取文章段落字符串
                # print('target_text is \n', target_text)
                num_list = num_get(target_text)                 # 从文章字符串中提取数字
                print(targets_date[i])
                print('num_list is \n', num_list)
                targets_date_write_in = []
                targets_date_write_in.append(targets_date[i])   # 将日期date添加到新的列表,当下只有日期一个元素
                if len(num_list) > 0:
                    content.writerow(targets_date_write_in + num_list)   # 将日期列表与数字列表合并,作为一行写入到CSV文件
                else:
                    pass   # 判断,如果num_list列表如果为空,则不进行写入,直接跳过
            except:
                pass

if __name__ == '__main__':
    main()

结果:截图示例如下
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值