美文网首页
python爬取8684公交网的全国信息

python爬取8684公交网的全国信息

作者: 指向远方的灯塔 | 来源:发表于2019-04-03 19:59 被阅读0次

js在线美化网址:https://www.html.cn/tool/js_beautify/
js在线解析网址:https://www.json.cn/#

思路分析:首先,进入首页https://www.8684.cn/,然后打开开发者工具,通过开发者工具观察网页变化,我们发现只有当我们【点击切换】的时候,才会有全国各地城市信息出现,如图:

图1
图2
这是局部网页的刷新,所以可能是ajax接口传送或者js文件中存在,通过点击这两处,发现数据在JS文件中,如图:
各城市的数据
利用json美化工具,将数据进行美化,发现数据是伪json数据,可以通过处理变成json数据(其中数据有按拼音和省份两种,选择一种即可,哪种方便选择哪种),然后通过json在线解析工具,解析json数据,所得数据如下:
解析后的一小部分数据
这样就可以获得全国的所有城市,然后将所有的城市分别与https://{城市名称}.8684.cn/进行拼接获得对应城市的公交首页,然后分别向对应的数字和字母开头发送请求获得所有的公交车链接,最后再向所有的公交车详情页发送请求,最后解析获得线路名称,运行时间,票价信息,公交公司,更新时间,线路长度,上行站个数,上行站牌,下行站个数,下行站牌等信息;代码实现如下:
import requests
import re
from bs4 import BeautifulSoup
import json
import time
import os
from multiprocessing import Pool

# 定制请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36',
    'Referer': 'https://www.8684.cn/'
}
def demo(city, url_begin, dirname):
    filename = str(city) + '.txt'
    filepath = os.path.join(dirname, filename)
    fp = open(filepath, 'w', encoding='utf8')
    url_city = url_begin.format(city)
    # print(url_city)
    # exit()
    # 向一级页面发送请求,得到所有的以数字开头或者字母开头的列表
    number_char_href_list = parse_first_page(url_city)
    # 遍历这个列表,依次向每个url发送请求
    for nchref in number_char_href_list:
        # 向二级页面,发送请求,得到所有的以1,2,3...开头的所有公交的url
        href_list = parse_second_page(url_city, nchref)
        # 遍历所有的href_list,依次向每个公交url发送请求,挨个解析
        for href in href_list:
            parse_third_page(href, fp)
    fp.close()
def parse_first_page(url_city):
    r = requests.get(url=url_city, headers=headers)
    soup = BeautifulSoup(r.text, 'lxml')
    #得到所有的以数字开头的链接
    number_a_list = soup.select('.bus_kt_r1 > a')
    #得到所有的以字母开头的链接
    char_a_list = soup.select('.bus_kt_r2 > a')
    all_a_list = number_a_list + char_a_list
    # print(len(all_a_list))
    # exit()
    all_href_list = []
    #得到所有a对象的href属性
    for oa in all_a_list:
        href = url_city.rstrip('/') + oa['href']
        all_href_list.append(href)
        time.sleep(2)
    # print(len(all_href_list))
    # exit()
    return all_href_list
def parse_second_page(url_city,nchref):
    r = requests.get(url=nchref, headers=headers)
    soup = BeautifulSoup(r.text, 'lxml')
    #获得所有的以某某开头的链接
    a_list = soup.select('#con_site_1 > a')
    #获得所有的公交链接
    href_list = []
    for oa in a_list:
        href = url_city.rstrip('/') + oa['href']
        href_list.append(href)
        time.sleep(2)
    return href_list
def parse_third_page(href,fp):
    r = requests.get(url=href, headers=headers)
    soup = BeautifulSoup(r.text, 'lxml')
    #获取线路名称
    route_name = soup.select('.bus_i_t1 > h1')[0].string
    print('正在爬取---%s---....' % route_name)
    #获取运行时间
    run_time = soup.select('.bus_i_content > p')[0].string
    #获取票价信息
    piao_info = soup.select('.bus_i_content > p')[1].string
    #获取公交公司
    company = soup.select('.bus_i_content > p > a')[0].string
    #获取更新时间
    update_time = soup.select('.bus_i_content > p')[3].string.lstrip('最后更新:')
    #获取路线长度
    try:
        route_length = soup.select('.bus_label > p')[0].string.strip('全程公里。')
    except Exception as e:
        route_length = '没有长度'
    #获取上行总站个数
    up_total = soup.select('.bus_line_top > span')[0].string.strip('共站').strip()
    up_site_name_list = []
    #获取得到所有的站牌
    all_a_list = soup.select('.bus_line_site > .bus_site_layer > div > a')
    #获取得到上行所有站牌
    up_a_list = all_a_list[:int(up_total)]
    for oa in up_a_list:
        up_site_name_list.append(oa.string)
    try:
        #获取下行总站个数
        down_total = soup.select('.bus_line_top > span')[1].string.strip('共站').strip()
        #获取下行站牌
        down_a_list = all_a_list[int(up_total):]
        down_site_name_list =[]
        for oa in down_a_list:
            down_site_name_list.append(oa.string)
    except Exception as e:
        down_total = '没有下行'
        down_site_name_list = []
    #将信息保存到字典中
    item = {
        '线路名称': route_name,
        '运行时间': run_time,
        '票价信息': piao_info,
        '公交公司': company,
        '更新时间': update_time,
        '线路长度': route_length,
        '上行站个数': up_total,
        '上行站牌': up_site_name_list,
        '下行站个数': down_total,
        '下行站牌': down_site_name_list,

    }
    string = json.dumps(item, ensure_ascii=False)
    fp.write(string + '\n')
    time.sleep(2)
    print('结束爬取--%s---' % route_name)
def main():
    t1 = time.time()
    url = 'https://js.8684.cn/citys/city_boxInf.min.js'
    #发送请求获得响应
    r = requests.get(url=url, headers=headers)
    #获得内容
    content = r.text
    #解析这个js文件,获取所有的城市列表
    string = content.split('=')[-1].rstrip(';')
    #正则提取所有城市拼音
    pattern = re.compile(r'([a-z]+):')
    # print(string)
    ret = pattern.findall(string)
    #print(len(ret))#452个城市
    url_begin = 'https://{}.8684.cn/'
    pol = Pool(24)
    dirname = 'gongjiao'
    for city in ret:
        pol.apply_async(demo, (city, url_begin,dirname))
    #关闭池子,不允许添加任务
    pol.close()
    #让主进程等待
    pol.join()
    print('主进程-子进程全部结束')
    t2 = time.time()
    print(t2-t1)
if __name__ == '__main__':
    main()

进程池 开24个进程,时间3个多小时,数据大小58.7M

相关文章

网友评论

      本文标题:python爬取8684公交网的全国信息

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