1. 程式人生 > >小白學 Python 爬蟲(42):春節去哪裡玩(系列終篇)

小白學 Python 爬蟲(42):春節去哪裡玩(系列終篇)

人生苦短,我用 Python

前文傳送門:

小白學 Python 爬蟲(1):開篇

小白學 Python 爬蟲(2):前置準備(一)基本類庫的安裝

小白學 Python 爬蟲(3):前置準備(二)Linux基礎入門

小白學 Python 爬蟲(4):前置準備(三)Docker基礎入門

小白學 Python 爬蟲(5):前置準備(四)資料庫基礎

小白學 Python 爬蟲(6):前置準備(五)爬蟲框架的安裝

小白學 Python 爬蟲(7):HTTP 基礎

小白學 Python 爬蟲(8):網頁基礎

小白學 Python 爬蟲(9):爬蟲基礎

小白學 Python 爬蟲(10):Session 和 Cookies

小白學 Python 爬蟲(11):urllib 基礎使用(一)

小白學 Python 爬蟲(12):urllib 基礎使用(二)

小白學 Python 爬蟲(13):urllib 基礎使用(三)

小白學 Python 爬蟲(14):urllib 基礎使用(四)

小白學 Python 爬蟲(15):urllib 基礎使用(五)

小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖

小白學 Python 爬蟲(17):Requests 基礎使用

小白學 Python 爬蟲(18):Requests 進階操作

小白學 Python 爬蟲(19):Xpath 基操

小白學 Python 爬蟲(20):Xpath 進階

小白學 Python 爬蟲(21):解析庫 Beautiful Soup(上)

小白學 Python 爬蟲(22):解析庫 Beautiful Soup(下)

小白學 Python 爬蟲(23):解析庫 pyquery 入門

小白學 Python 爬蟲(24):2019 豆瓣電影排行

小白學 Python 爬蟲(25):爬取股票資訊

小白學 Python 爬蟲(26):為啥買不起上海二手房你都買不起

小白學 Python 爬蟲(27):自動化測試框架 Selenium 從入門到放棄(上)

小白學 Python 爬蟲(28):自動化測試框架 Selenium 從入門到放棄(下)

小白學 Python 爬蟲(29):Selenium 獲取某大型電商網站商品資訊

小白學 Python 爬蟲(30):代理基礎

小白學 Python 爬蟲(31):自己構建一個簡單的代理池

小白學 Python 爬蟲(32):非同步請求庫 AIOHTTP 基礎入門

小白學 Python 爬蟲(33):爬蟲框架 Scrapy 入門基礎(一)

小白學 Python 爬蟲(34):爬蟲框架 Scrapy 入門基礎(二)

小白學 Python 爬蟲(35):爬蟲框架 Scrapy 入門基礎(三) Selector 選擇器

小白學 Python 爬蟲(36):爬蟲框架 Scrapy 入門基礎(四) Downloader Middleware

小白學 Python 爬蟲(37):爬蟲框架 Scrapy 入門基礎(五) Spider Middleware

小白學 Python 爬蟲(38):爬蟲框架 Scrapy 入門基礎(六) Item Pipeline

小白學 Python 爬蟲(39): JavaScript 渲染服務 Scrapy-Splash 入門

小白學 Python 爬蟲(40):爬蟲框架 Scrapy 入門基礎(七)對接 Selenium 實戰

小白學 Python 爬蟲(41):爬蟲框架 Scrapy 入門基礎(八)對接 Splash 實戰

引言

首先恭喜看到這篇文章的同學,本篇內容為 「小白學 Python 爬蟲」 系列的最後一篇。

看了下上面的前文傳送門,加上這篇內容,總共有 42 篇,小編還是成就感滿滿,小編翻看了下公眾號,第一篇文章是在 2019 年的 11 月 17 日推送的,大致數了數,將近兩個月的時間。

當然,其中一些文章的質量並不高,很多都是在比較有限的時間中趕工趕出來的,還是感謝各位讀者對小編的不離不棄,寫的這麼爛還沒取關的絕對是真愛了。

正好下週就要過年了,從推送的時間算的話還有 10 個自然日左右的時間,可能很多同學可能過年是要出去玩的,那麼去哪裡玩就成了一個問題。

那麼,怎麼挑選去哪裡玩最快的,小編想了想,直接去抓某站的資料吧,抓下來自己根據自己的情況查詢下就好了。

那麼今天的目標站是:馬蜂窩。

這裡小編還想說一點,雖然我們在前面 7、 8 篇文章中都是在講如何使用爬蟲框架 Scrapy ,說實話,小編並不覺得 Scrapy 有多方便,在一些簡單的應用場景下,使用 Requests 庫可能是最方便的選擇, Scrapy 小編個人感覺還是更適合使用在一些中大型的爬蟲專案中,簡單的爬蟲指令碼使用最簡單的技術棧就 ok 了,所以小編在本文中使用的技術棧還是 Requests + PyQuery 。

不要問為啥,問就是喜歡。

分析

首先我們訪問連結,開啟我們將要抓取的站點:https://www.mafengwo.cn/gonglve/ 。

這裡是攻略的列表頁,我們的目標是抓取來自遊記的資料,其餘的資料放過,原因是在遊記中我們才能獲取到一些具體的我們需要的資料。

資料的來源搞清楚了,接下來是翻頁功能,只有清楚瞭如何翻頁,我們才能源源不斷的獲取資料,否則就只能抓取第一頁的資料了。

當把頁面翻到最下面的時候就尷尬了,發現是自動載入更多,這個當然難不倒帥氣逼人的小編我,掏出大殺器, Chrome 的開發者工具 F12 ,選到 network 標籤頁,再往下滾動一下,我們檢視下這個頁面發出的請求。

這個請求很有意思,請求的路徑和我們訪問的頁面路徑一樣,但是請求型別變成 POST ,並且增加了請求引數,型別還是 Form 表單格式的。

截止這裡,我們已經清楚了目標站點的資料路徑以及翻頁方式,雖然目前我們並不知道最大頁數是多少,但是我們可以人為的設定一個最大頁數,比如 100 或者 200 ,小編相信,這麼大的站點上,幾百頁的遊記應該是還有的。

程式碼

程式碼小編就直接貼出來,之前有同學希望資料是儲存在 Excel 中的,本次實戰的資料就不存資料庫了,直接寫入 Excel 。

import requests
from pyquery import PyQuery
import xlsxwriter

headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36',
    'cookie': '__jsluid_s=6fc5b4a3b5235afbfdafff4bbf7e6dbd; PHPSESSID=v9hm8hc3s56ogrn8si12fejdm3; mfw_uuid=5e1db855-ab4a-da12-309c-afb9cf90d3dd; _r=baidu; _rp=a%3A2%3A%7Bs%3A1%3A%22p%22%3Bs%3A18%3A%22www.baidu.com%2Flink%22%3Bs%3A1%3A%22t%22%3Bi%3A1579006045%3B%7D; oad_n=a%3A5%3A%7Bs%3A5%3A%22refer%22%3Bs%3A21%3A%22https%3A%2F%2Fwww.baidu.com%22%3Bs%3A2%3A%22hp%22%3Bs%3A13%3A%22www.baidu.com%22%3Bs%3A3%3A%22oid%22%3Bi%3A1026%3Bs%3A2%3A%22dm%22%3Bs%3A15%3A%22www.mafengwo.cn%22%3Bs%3A2%3A%22ft%22%3Bs%3A19%3A%222020-01-14+20%3A47%3A25%22%3B%7D; __mfwothchid=referrer%7Cwww.baidu.com; __omc_chl=; __mfwc=referrer%7Cwww.baidu.com; Hm_lvt_8288b2ed37e5bc9b4c9f7008798d2de0=1579006048; uva=s%3A264%3A%22a%3A4%3A%7Bs%3A13%3A%22host_pre_time%22%3Bs%3A10%3A%222020-01-14%22%3Bs%3A2%3A%22lt%22%3Bi%3A1579006046%3Bs%3A10%3A%22last_refer%22%3Bs%3A137%3A%22https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DuR5Oj9n_xm4TSj7_1drQ1HRnFTYNM0M2TCljkjVrdIiUE-B2qPgh0MifEkceLE_U%26wd%3D%26eqid%3D93c920a80002dc72000000035e1db85c%22%3Bs%3A5%3A%22rhost%22%3Bs%3A13%3A%22www.baidu.com%22%3B%7D%22%3B; __mfwurd=a%3A3%3A%7Bs%3A6%3A%22f_time%22%3Bi%3A1579006046%3Bs%3A9%3A%22f_rdomain%22%3Bs%3A13%3A%22www.baidu.com%22%3Bs%3A6%3A%22f_host%22%3Bs%3A3%3A%22www%22%3B%7D; __mfwuuid=5e1db855-ab4a-da12-309c-afb9cf90d3dd; UM_distinctid=16fa418373e40f-070db24dfac29d-c383f64-1fa400-16fa418373fe31; __jsluid_h=b3f11fd3c79469af5c49be9ecb7f7b86; __omc_r=; __mfwa=1579006047379.58159.3.1579011903001.1579015057723; __mfwlv=1579015057; __mfwvn=2; CNZZDATA30065558=cnzz_eid%3D448020855-1579003717-https%253A%252F%252Fwww.baidu.com%252F%26ntime%3D1579014923; bottom_ad_status=0; __mfwb=5e663dbc8869.7.direct; __mfwlt=1579019025; Hm_lpvt_8288b2ed37e5bc9b4c9f7008798d2de0=1579019026; __jsl_clearance=1579019146.235|0|fpZQ1rm7BHtgd6GdjVUIX8FJJ9o%3D'
}


s = requests.Session()


value = []

def getList(maxNum):
    """
    獲取列表頁面資料
    :param maxNum: 最大抓取頁數
    :return:
    """
    url = 'http://www.mafengwo.cn/gonglve/'
    s.get(url, headers = headers)
    for page in range(1, maxNum + 1):
        data = {'page': page}
        response = s.post(url, data = data, headers = headers)
        doc = PyQuery(response.text)
        items = doc('.feed-item').items()
        for item in items:
            if item('.type strong').text() == '遊記':
                # 如果是遊記,則進入內頁資料抓取
                inner_url = item('a').attr('href')
                getInfo(inner_url)


def getInfo(url):
    """
    獲取內頁資料
    :param url: 內頁連結
    :return:
    """
    response = s.get(url, headers = headers)
    doc = PyQuery(response.text)
    title = doc('title').text()
    # 獲取資料採集區
    item = doc('.tarvel_dir_list')
    if len(item) == 0:
        return
    time = item('.time').text()
    day = item('.day').text()
    people = item('.people').text()
    cost = item('.cost').text()
    # 資料格式化
    if time == '':
        pass
    else:
        time = time.split('/')[1] if len(time.split('/')) > 1 else ''

    if day == '':
        pass
    else:
        day = day.split('/')[1] if len(day.split('/')) > 1 else ''

    if people == '':
        pass
    else:
        people = people.split('/')[1] if len(people.split('/')) > 1 else ''

    if cost == '':
        pass
    else:
        cost = cost.split('/')[1] if len(cost.split('/')) > 1 else ''


    value.append([title, time, day, people, cost, url])


def write_excel_xlsx(value):
    """
    資料寫入Excel
    :param value:
    :return:
    """
    index = len(value)

    workbook = xlsxwriter.Workbook('mfw.xlsx')
    sheet = workbook.add_worksheet()
    for i in range(1, index + 1):
        row = 'A' + str(i)
        sheet.write_row(row, value[i - 1])
    workbook.close()
    print("xlsx格式表格寫入資料成功!")


def main():
    getList(5)
    write_excel_xlsx(value)

if __name__ == '__main__':
    main()

因為馬蜂窩在遊記的詳情頁面上有反爬的限制,小編這裡為了簡單,直接從瀏覽器中將 cookie copy 出來,加在了請求頭上。

小編這裡簡單的爬取了 5 個列表頁的資訊,如下:

好像資料量並不是很多的樣子,各位同學可以嘗試爬取 50 頁或者 100 頁的資料,這樣得到的結果會有比較不錯的參考價值。

好了,本篇內容到這裡就結束了,小編隨後會將全部的文章索引整理出來推在公眾號上,方便大家查閱。

示例程式碼

本系列的所有程式碼小編都會放在程式碼管理倉庫 Github 和 Gitee 上,方便大家取用。

示例程式碼-Github

示例程式碼-Gi