用Scrapy框架爬取公交线路站点信息的方法

1 篇文章 0 订阅
1 篇文章 0 订阅

关于爬取公交线路,网上一搜有很多,大部分都是从8684,图吧公交爬取数据,都能爬到相关线路,票价,时间,站点等信息,但是却无法爬取到站点的坐标信息,以及线路的坐标信息,但是这些坐标信息又是非常重要的,所以本文综合爬取8846和爬取高德地图站点信息坐标完成公交线路信息的获取。

说一下主要步骤

1.搭建scrapy框架

这个度娘一大堆,可以参考https://www.mscto.com/python/507221.htmlhttps://blog.csdn.net/zjiang1994/article/details/52779537https://blog.csdn.net/aibiabcheng/article/details/105525779等文章

2.爬取8648**市的公交线路

我们打开8648网站可以看到,8648里面包括所有公交线路的列表

我们通过解析html网页,获取到以数字开头和字母开头的所有公交线路,主要代码如下

        a_list = response.xpath(
            "//div[@class='bus-layer depth w120']/div[@class='pl10'][1]/div[@class='list']/a/@href").extract()
        all_urls = [response.url + a.strip("/") for a in a_list]  # url前缀列表
        a_list2 = response.xpath(
            "//div[@class='bus-layer depth w120']/div[@class='pl10'][2]/div[@class='list']/a/@href").extract()
        all_urls2 = [response.url + a.strip("/") for a in a_list2]  # url前缀列表
        all_urls = all_urls+all_urls2

主要通过解析div的class获取到每个list的href再进行解析

获取到每个线路的链接后,我们再对每个线路的链接网页进行解析

这样的话,我们就得到所有的合肥市的公交线路

3.遍历每一条线路,再对每一条线路进行高德地图api请求,得到每一条线路的站点信息,票价信息,公司信息等,具体的可以参考文章https://zhuanlan.zhihu.com/p/141378209

url = 'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=559bdffe35eec8c8f4dae959451d705c&output=json&city={}&offset=2&keywords={}&platform=JS'.format('合肥', line_name)来获得整个线路的信息,全部代码如下
import scrapy
from ..items import CityItem
from lxml import etree
import requests
import json
import  re
import time
class BaiduSpider(scrapy.Spider):
    name = 'busline'

    start_urls = {
        "https://{}.8684.cn/".format('hefei'),
    }

    def parse(self, response):
        items = []
        a_list = response.xpath(
            "//div[@class='bus-layer depth w120']/div[@class='pl10'][1]/div[@class='list']/a/@href").extract()
        all_urls = [response.url + a.strip("/") for a in a_list]  # url前缀列表
        a_list2 = response.xpath(
            "//div[@class='bus-layer depth w120']/div[@class='pl10'][2]/div[@class='list']/a/@href").extract()
        all_urls2 = [response.url + a.strip("/") for a in a_list2]  # url前缀列表
        all_urls = all_urls+all_urls2
        for a in all_urls:
            print(a)
            tree = etree.HTML(requests.get(url=a).text)
            detail_href = tree.xpath("//div[@class='list clearfix']/a/@href")
            for detail in detail_href:
                all_urls_1 = response.url + detail.strip("/")
                tree = etree.HTML(requests.get(url=all_urls_1).text)
                # 公交线路名称
                line_name = tree.xpath("//div[@class='layout-left']/div[@class='bus-lzinfo mb20']//h1/text()")[0]
                index = line_name.find('公交车路线')
                line_name=line_name[2:index]
                time.sleep(2)
                #请求线路经过站点数据
                url = 'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=559bdffe35eec8c8f4dae959451d705c&output=json&city={}&offset=2&keywords={}&platform=JS'.format('合肥', line_name)
                r = requests.get(url).text
                rt = json.loads(r)
                if rt['buslines']:
                    if len(rt['buslines']) == 0:  # 有名称没数据
                        print(line_name+'没有数据!')
                    else:
                        #获取站点数据
                     for cc in range(len(rt['buslines'])):
                         up_down=cc
                         bus_setop = rt['buslines'][cc]["start_stop"]+"-"+rt['buslines'][cc]["end_stop"]
                         bus_cost = rt['buslines'][cc]["total_price"]
                         bus_type = rt['buslines'][cc]["type"]
                         bus_polyline = rt['buslines'][cc]["polyline"]
                         bus_company= rt['buslines'][cc]["company"]
                         for station_list in rt['buslines'][cc]['busstops']:
                             lineItem = CityItem()
                             lineItem["bus_name"] = line_name
                             #上下行
                             lineItem["bus_direction"] = up_down
                             # 起始点
                             lineItem["bus_setop"] = bus_setop
                             #站点
                             lineItem["bus_station"] = station_list["name"]
                             #坐标
                             lineItem["bus_location"] = station_list["location"]
                             #站点序号
                             lineItem["bus_sequence"] = station_list["sequence"]
                             #票价
                             lineItem["bus_cost"] = bus_cost
                             #类型
                             lineItem["bus_type"] = bus_type
                             #线路Polyline
                             lineItem["bus_polyline"] = bus_polyline
                             #所属公司
                             lineItem["bus_company"] = bus_company
                             print(lineItem)
                             items.append(lineItem)
        return items

4.导出csv文件,在pipelines.py写入如下代码:

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


# useful for handling different item types with a single interface
from itemadapter import ItemAdapter

from scrapy.exporters import CsvItemExporter
import csv
import json
class FisrtpjPipeline:
    def process_item(self, item, spider):
        # 写入spider传过来的具体数值
        self.writer.writerow(item)
        # 写入完返回
        return item
    # 保存为csv格式
    def __init__(self):
        # 打开文件,指定方式为写,利用第3个参数把csv写数据时产生的空行消除
        self.f = open("myproject.csv", "a", newline="")
        # 设置文件第一行的字段名,注意要跟spider传过来的字典key名称相同
        self.fieldnames = ["bus_name", "bus_direction", "bus_setop", "bus_station", "bus_location", "bus_sequence",
                           "bus_cost", "bus_type", "bus_polyline", "bus_company"]
        # 指定文件的写入方式为csv字典写入,参数1为指定具体文件,参数2为指定字段名
        self.writer = csv.DictWriter(self.f, fieldnames=self.fieldnames)
        # 写入第一行字段名,因为只要写入一次,所以文件放在__init__里面
        self.writer.writeheader()


    def close(self, spider):
        self.f.close()

5.配置好后,新建start.py写入如下代码

6.完成爬取后,我们开始csv文件,便得到了我们想要的数据

本文所有代码已上传github地址为https://github.com/wengjidong/ww2.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值