這兩天滴滴剛出事,主要的一個原因就在於遇害人家屬向滴滴求助,想獲得罪犯的行駛路徑等被拒,這是一個很壞的事件。

現在我們把關注點放在路徑上,如GPX。你可以想像GPX是路徑散點的連線,那對於普通的科研者而言,自己難以大量產生自然的軌跡數據,而又需要相關的研究時,只能向網站爬取。

臺灣的GPX步行數據,我們可以從以下一個相關愛好者社羣獲得

也就是說,我們可以從這網站去獲取相關的GPX數據,可以看到這個網站所有數據都編排好了,尤其以城市劃分

我們以臺北市為代表,發現總共有695條gpx數據

點擊去看看,詳細頁面

這個數據的有半部分,可以有詳細的描述,所以,除了可以獲得GPX的下載鏈接之外,還能夠獲得相關的gpx簡介,該咋做呢?

來分析一下網頁的連接

https://tw.hiking.biji.co/index.php?q=trail&act=gpx_list&city=16&keyword=&page=1

發現其中有兩個屬性,一個是city,講明是哪個城市;另一是page,說明是第幾頁。於是我們只要指定城市和對於的page,就能夠找到所有的路徑詳細頁面,然後再下載其中的內容。

但運行過程中發現一個問題,詳細頁面的介紹是js載入的,無法直接爬取html獲得

所以,這裡我採用webdriver的方式,通過瀏覽器真實訪問網頁來獲得其中的內容。

好啦,以上就是我們想做的事情,那我們來看看代碼怎麼實現

選擇會用到的Packages

import re
import urllib.request
import requests
from urllib import parse, request
from bs4 import BeautifulSoup
from selenium import webdriver

指定好城市的鏈接,具體的頁數你需要自己去看,或者通過代碼查找也行

pageUrls = [https://tw.hiking.biji.co/index.php?q=trail&act=gpx_list&city=16&keyword=&page={}.format(i for i in range(1, 36))]

之後是遍歷所有的路徑列表,獲得每個路徑的單獨link

def get_single_html(onePageUrl):
r = requests.get(onePageUrl)
soup = BeautifulSoup(r.text, "lxml")
return soup

獲得單個link,這裡用BeautifulSoup及正則表達式來匹配對應的標籤,獲取內容

def get_detail_url(single_html):
detail = []
for x in single_html.find_all(a, href = re.compile(gpx_detail&id)):
link = x.get(href)
if link:
newLink = http://tw.hiking.biji.co + link
detail.append(newLink)

#List中每個都有重複的,所以現在要去除重複的元素
detail = list(set(detail))
# 單個頁面的所有軌跡的路線,存為detail list
return detail

正式獲得所有的路徑links

def get_all_url(pageUrls):
allUrl = []
for onePage in pageUrls:
#獲得某頁中的所有html元素
single_html = get_single_html(onePage)

detail = get_detail_url(single_html)
allUrl = detail + allUrl
return allUrl

allUrl = get_all_url(pageUrls)
print(總共獲取{}個links.format(len(allUrl)))

這時,該開始下載內容了,這裡用webdriver,原本使用firefox來打開,但後來發現firefox速度太慢了,就改用chrome,速度槓槓的

def get_soup_byDriver(url):
driver = webdriver.Chrome()

driver.get(url)
data = driver.page_source
soup = BeautifulSoup(data, lxml)

#都說用quit()來關閉瀏覽器,結果close()才生效了
driver.quit()
print(正在下載{}.format(url))
return soup

這裡是,用chrome打開每個鏈接,然後獲得其中的頁面信息,再用soup匹配下來

def get_allUrl_soup(allUrl):
#存放所有url的soup,用dict的key,可以將soup編號
soupList = []
for url in allUrl:
oneSoup = get_soup_byDriver(url)
soupList.append(oneSoup)

return soupList

先運行一遍,把所有路徑頁面都爬下來

soupList = get_allUrl_soup(allUrl[630:644])

好啦,趴下來之後,再一個頁面一個頁面來匹配自己需要的內容

detailsDictList = []

for i in range(3):
soup = soupList[i]
print(現在是第{}.format(i))
a = {}

allDetail = soup.find_all(div, class_="detail-content")

a[路線名稱] = allDetail[0].text
a[出發日期] = allDetail[1].text
a[距離] = allDetail[2].text
a[總花費時間] = allDetail[3].text
a[高度落差] = allDetail[4].text
a[總爬升高度] = allDetail[5].text
a[總下降高度] = allDetail[6].text
a[相關路線] = allDetail[7].text

print(第{}個數據處理好了.format(i))

detailsDictList.append(a)

來看看效果

好啦,把所有內容都保存下來,再存成csv

allList = []
for i in detailsDictList:
oneList = []
for k, v in i.items():
oneList.append(str(v))
allList.append(oneList)

這裡又用上了pandas

import pandas as pd
df = pd.DataFrame(allList)
df.to_excel(/Users/vincentyau/Desktop/Taipei_gpx_data3.xlsx)

以上就是簡單獲取gpx中的內容啦,如果要下載gpx的話,就將匹配路徑頁面的內容改成gpx就好了。

還有啥,大boss還需要我下載每條路徑的評論,所以我在修改一些方法,現在還在改。

以上的方式有幾個問題:

  1. 載入的速度還不夠快,webdriver需要一條一條鏈接打開,幾百條數據還行,但是數據量要再大的話,就挺麻煩的。
  2. Python的使用還不夠成熟,優化更加不夠,定義的函數也不夠嚴謹,復用率低。

推薦閱讀:

查看原文 >>
相關文章