天天看點

攜程旅遊網與馬蜂窩遊客記錄爬取

前言:這是我學習Python爬蟲以來,第一次使用python進行大規模的進行資料挖掘。邀請我加入她們科研項目的是工商學院的彭老師,做一個關于避暑旅遊的課題。當他們需要擷取攜程旅遊筆記時,由于文章的内容太多,思路也沒有考慮好,無法使用資料采集器把筆記放入Excel。于是找到了我們資訊學院尋求方法幫助,我的輔導員老師就向她推薦了我。終于有機會進行大型的項目實戰了,非常幸運能參與這次的項目。但也由于平時比較繁忙,真正開發的時間并不是很多,通常都是課餘時間做的。

第一次項目交接

她安排她的學生黃超來與我進行交接,告訴我,他們的需求。以前資料的采集就是他負責的,是以需求還是非常清楚的。他打電話與我溝通,說需要把旅遊的筆記放進Excel做資料分析,我不是很了解,對于這些不規則的文本,最好的方式應該是放進txt文本才友善呀,經過一些溝通後,确定第二天見面談。我需要在周末上雙學位的課程,10月13号下午下課後就在我們上課的教室讨論,指出我需要爬取的内容。

當天也相當于交流學習,我從未做過這方面的實戰。聽他的要求後,最理想的方式是把它文字儲存在txt文本,并不是Excel,初步達成共識。

第一次爬取:攜程網,遊客遊記,關鍵詞“避暑旅遊”,不限時間,初次搜尋出4398條

攜程旅遊網與馬蜂窩遊客記錄爬取

由于數量太大,更改關鍵詞為“避暑”,時間為1年内,遊記,共找到800篇,作為這次爬取的目标。由于是初次做這樣的工作,變弄便溝通,花了3多小時的時間才完成初步的工作,實作思路如下:

實作思路第一步:爬取一篇文本做測試

1.1.1、擷取單篇文章遊客筆記文本

攜程旅遊網與馬蜂窩遊客記錄爬取

通過分析HTML發現,我所需要擷取的文字都在

class="ctd_content"

這個标簽類,直接通過BeautifulSoup的find子產品找到所有的文本就可以了;

攜程旅遊網與馬蜂窩遊客記錄爬取

運作結果如下:

攜程旅遊網與馬蜂窩遊客記錄爬取

1.1.2、儲存擷取的内容到txt文本

txt = str(txt)#把擷取的内容轉換為字元,建議使用
filename = 'D:write_data.txt'
with open(filename,'w',encoding='utf-8') as f: # 如果filename不存在會自動建立, 'w'表示寫資料,寫之前會清空檔案中的原有資料!
    f.write(txt)
    f.close()
           

txt截屏:

攜程旅遊網與馬蜂窩遊客記錄爬取

經驗:為什麼要把擷取到的内容轉化為字元串?

我在寫入txt的過程中,發現很多文本會提示類型有有誤,轉成字元串後就沒有報錯了。

現在算是成功最主要的一步了,接下來就是爬取所有的文章了。

實作思路第二步:擷取所有文本連結

1.2.1、擷取一個首頁的所有文章連結

import requests
from lxml import etree
url = 'https://you.ctrip.com/searchsite/travels/?query=避暑&isAnswered=&isRecommended=&publishDate=365&PageNo=1'
html = requests.get(url).text
txt = etree.HTML(html)
file = txt.xpath('/html/body/div[2]/div[2]/div[2]/div/div[1]/ul/li')
for t in file:
    href = t.xpath('./dl/dt/a/@href')[0]
    hrefUrl = 'https://you.ctrip.com'+href#把連結補充完整
    print (hrefUrl)
           

擷取結果:

攜程旅遊網與馬蜂窩遊客記錄爬取

注意: 攜程網使用的是相對路徑,我們需要把擷取的連結補充完整,在前面加上“https://you.ctrip.com”,

1.2.1、擷取每個首頁的連結

攜程旅遊網與馬蜂窩遊客記錄爬取

1.2.1、擷取每個首頁的所有文章連結,并添加到數組

為什麼要把擷取到的連結存在數組,不是直接進行擷取它的内容?

1、從數組内周遊出來速度比單獨爬取一個會更快

2、減少被反爬的機率,經常通路更容易被識别出爬蟲

3、優化邏輯

import requests
from lxml import etree
from bs4 import BeautifulSoup

headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'
}
allUrl = []
for num in range(1,81,1):
    print(num)
    url = 'https://you.ctrip.com/searchsite/travels/?query=避暑&isAnswered=&isRecommended=&publishDate=365&PageNo='+str(num)
    html = requests.get(url).text
    txt = etree.HTML(html)
    file = txt.xpath('/html/body/div[2]/div[2]/div[2]/div/div[1]/ul/li')
    for t in file:
        href = t.xpath('./dl/dt/a/@href')[0]
        hrefUrl = 'https://you.ctrip.com'+href
        allUrl.append(hrefUrl)
           

1.2.1、開始擷取所有的文章

import requests
from lxml import etree
from bs4 import BeautifulSoup

headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'
}
k = 0
allUrl = []
for num in range(1,81,1):
    print(num)
    url = 'https://you.ctrip.com/searchsite/travels/?query=避暑&isAnswered=&isRecommended=&publishDate=365&PageNo='+str(num)
    html = requests.get(url).text
    txt = etree.HTML(html)
    file = txt.xpath('/html/body/div[2]/div[2]/div[2]/div/div[1]/ul/li')
    for t in file:
        href = t.xpath('./dl/dt/a/@href')[0]
        hrefUrl = 'https://you.ctrip.com'+href
        allUrl.append(hrefUrl)
        
for useUrl in allUrl:
    k = k + 1
    print ("正在擷取第%s篇"%k)
    print (useUrl)
    html = requests.get(url = useUrl,headers=headers).text
    soup = BeautifulSoup(html, "html.parser")
    t = soup.find(attrs={"class": "ctd_content"})
    txt = t.get_text().replace("\n","")
    txt = str(txt)
    filename = 'G:write_data.txt'
    with open(filename,'a',encoding='utf-8') as f: # 如果filename不存在會自動建立, 'w'表示寫資料,寫之前會清空檔案中的原有資料!
        f.write(txt)
        f.close()
print ("擷取完畢!")
           

幸運點:

1、還好這次的運氣比較好,沒有遇見伺服器請求失敗的情況,一氣呵成

2、網頁結構統一,沒有出現結構異常而報錯

更具他留下來的要求,還需要爬取攜程網的問答子產品,馬蜂窩的三個子產品,分别是關鍵詞為“避暑”的遊記,攻略和問答。

第二天,我在上課的時間完成了對攜程網問答子產品的爬取,并把完成的文本發給他先做研究。晚上的時候,他告訴我說,他們老師想見我,和我仔細的交流一下。

第二次項目交接

周二,我白天要上班到16:30,我晚上還要上三節課,通過電話約定16:40去找她,簡單的交流一下。這次說是項目交接,還不如說叫做聊天吧,彭老師告訴我她們在做什麼項目,并且完成的進度,對技術人員的需求。接下來我就是向她展示了一下我爬取資料的思路,友善她在寫文稿的時候有相關的思路,并且簡單的确認了一下接下來資料的擷取。

在她看來,會一門别人不會的技術,在做學術上是有很大優勢的。而我所掌握的網絡爬蟲就是一門不錯的技術,希望我能做好這門技術,給講了很多考研和做學術的事。多參與這類項目的開發,并發表相關的論文,對我考研是有很大幫助的,但對于考研的事情,我并沒有明确自己的目标。

經過交談,她也想學習Python爬蟲,并讓我有時間的時候指導一下學習,後來幫她安裝好了學習Python的編譯,給了一些入門基礎教程,讓她先了解一下基礎,以後再教授爬蟲實戰和對付反爬等相關工作。

當天晚上,我開始對馬蜂窩的資料進行了爬取實戰。

最近有人使用資料采集器爬了馬蜂窩的1800萬資料就刷爆了網絡,驚動了網際網路界和投資界,背後的資料團隊也是以爆紅。是以它的資料又重新做好保護措施,我這次爬取它還是花了一些時間來研究它的。請求到它的源碼後,發現我需要的資料都沒有在其中,這就有點麻煩了,隻能使用其他的辦法了。經過仔細的檢視後,我發現它的資料全部都是動态加載的,你看到哪裡,它就加載到哪裡,建立這個思維後,我開始使用selenium搞自動化,但是這個的效率就要慢很多了,還好不負努力,終于把它解決了,花了一節課的時間運作代碼,爬取了所有的遊記,共計46篇,速度已經慢得難受了,還好是上課時間,聽了一節課,不影響我時間的使用。

2.1.1、擷取首頁的所有文章連結,儲存到數組

import requests
from lxml import etree
from bs4 import BeautifulSoup
filename = 'G:馬蜂窩遊記筆記文本.txt'
noteBook = 'G:馬蜂窩遊記筆記評論.txt'

url = 'http://www.mafengwo.cn/search/q.php?q=%E9%81%BF%E6%9A%91&t=notes&seid=D8276190-E622-4B11-A1B6-DF09CF22DD76&mxid=&mid=&mname=&kt=1'
headers = {
    'Referer': 'http://www.mafengwo.cn/search/q.php?q=%E9%81%BF%E6%9A%91&t=notes&seid=D8276190-E622-4B11-A1B6-DF09CF22DD76&mxid=&mid=&mname=&kt=1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'
}
allUrl = []
htmlUrl = requests.get(url,headers = headers).text
txtUrl = etree.HTML(htmlUrl)
file = txtUrl.xpath('//*[@id="_j_search_result_left"]/div/div/ul/li')
for t in file:
    hrefUrl = t.xpath('./div/div[2]/h3/a/@href')[0]
    allUrl.append(hrefUrl)
 	print (hrefUrl)
print(len(allUrl))
           

部分截屏,一共擷取46條連結

攜程旅遊網與馬蜂窩遊客記錄爬取

2.1.2、打開文章,下拉加載資料

使用selenium對js進行操作

for t in range(1000,310000,1000):#第一次下拉1000像素,第二次要大于1000,相當于從零算起,310000是它的總像素
        time.sleep(0.1)#延時,模拟人為加載
        js=f"document.documentElement.scrollTop={t}"#下拉加載
        driver.execute_script(js)
           

2.1.3、加載資料完畢,擷取HTML,并關閉浏覽器

由于頁面太多,使用浏覽器的頁面後要關閉浏覽器,減少電腦CPU的消耗,也是桌面整潔

source = driver.page_source#擷取源碼
    driver.close()#關閉浏覽器
           

2.1.4、提取作者筆記和評論

# 提取作者筆記
    soup = BeautifulSoup(source, "html.parser")
    note = soup.find(attrs={"class": "_j_content_box"}).get_text()
    note = note.replace("\n","")
    note = str(note)
           
#提取筆記評論
    for usrAnswer in soup.find_all(attrs={"class": "mfw-cmt _j_reply_item"}):
        answer = usrAnswer.find(attrs={"class": "_j_reply_content"}).get_text()
        answer = str(answer)
           

2.1.5、分開儲存筆記和評論

分開儲存的目的主要是為了友善研究,她們并沒有提要求,到這樣做比較保險。

# 儲存作者筆記
    with open(filename,'a',encoding='utf-8') as f: # 如果filename不存在會自動建立, 'w'表示寫資料,寫之前會清空檔案中的原有資料!
        f.write(note+"\n")
        f.close()
           
#儲存筆記評論
        with open(noteBook,'a',encoding='utf-8') as g: # 如果filename不存在會自動建立, 'w'表示寫資料,寫之前會清空檔案中的原有資料!
            g.write(answer+"\n")
            g.close()
           

2.1.6、大功告成,開始批量爬取

from selenium import webdriver
import time
import requests
from lxml import etree
from bs4 import BeautifulSoup

filename = 'G:馬蜂窩遊記筆記文本.txt'
noteBook = 'G:馬蜂窩遊記筆記評論.txt'
url = 'http://www.mafengwo.cn/search/q.php?q=%E9%81%BF%E6%9A%91&t=notes&seid=D8276190-E622-4B11-A1B6-DF09CF22DD76&mxid=&mid=&mname=&kt=1'
headers = {
    'Referer': 'http://www.mafengwo.cn/search/q.php?q=%E9%81%BF%E6%9A%91&t=notes&seid=D8276190-E622-4B11-A1B6-DF09CF22DD76&mxid=&mid=&mname=&kt=1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'
}
allUrl = []
htmlUrl = requests.get(url,headers = headers).text
txtUrl = etree.HTML(htmlUrl)
file = txtUrl.xpath('//*[@id="_j_search_result_left"]/div/div/ul/li')
for t in file:
    hrefUrl = t.xpath('./div/div[2]/h3/a/@href')[0]
    allUrl.append(hrefUrl)
for urlUser in allUrl:
    print("正在爬取:",urlUser)
    driver = webdriver.Chrome('D:\\Software\\chromedriver.exe')
    driver.get(urlUser)#打開馬蜂窩
    driver.implicitly_wait(6)#等待加載六秒
    time.sleep(6)
    for t in range(1000,310000,1000):#第一次下拉1000像素,第二次要大于1000,相當于從零算起,310000是它的總像素
        time.sleep(0.1)#延時,模拟人為加載
        js=f"document.documentElement.scrollTop={t}"#下拉加載
        driver.execute_script(js)
    source = driver.page_source#擷取源碼
    driver.close()#關閉浏覽器
    # 提取作者筆記
    soup = BeautifulSoup(source, "html.parser")
    note = soup.find(attrs={"class": "_j_content_box"}).get_text()
    note = note.replace("\n","")
    note = str(note)
    # 儲存作者筆記
    with open(filename,'a',encoding='utf-8') as f: # 如果filename不存在會自動建立, 'w'表示寫資料,寫之前會清空檔案中的原有資料!
        f.write(note+"\n")
        f.close()
    #提取筆記評論
    for usrAnswer in soup.find_all(attrs={"class": "mfw-cmt _j_reply_item"}):
        answer = usrAnswer.find(attrs={"class": "_j_reply_content"}).get_text()
        answer = str(answer)
        #儲存筆記評論
        with open(noteBook,'a',encoding='utf-8') as g: # 如果filename不存在會自動建立, 'w'表示寫資料,寫之前會清空檔案中的原有資料!
            g.write(answer+"\n")
            g.close()
            
print ("該頁評論已下載下傳完畢!")
           

終于解決了,看以來還行~

攜程旅遊網與馬蜂窩遊客記錄爬取

2.1.7、更具這樣的思路,完成了馬蜂窩攻略和問答的爬取

馬蜂窩攻略和問答與遊記不同的地方在于,它倆的文章比較多,需要翻頁,這樣使用一個循環就構造好它的連結了,還是比較容易的,圓滿完成任務!

攜程旅遊網與馬蜂窩遊客記錄爬取

第三次項目交接

這次黃超同學重新更改了他的需求,需要重新爬取攜程網遊記,從以前的一年之内改為時間不限,從800篇變到了9331篇

攜程旅遊網與馬蜂窩遊客記錄爬取

這樣的任務量無疑增加得大了,如果是按照先前的方式運作代碼一篇一篇的爬取,在運作順利的情況下,估計也要花兩三個小時吧。是以必須解決速度問題… …

方法一——使用多程序:

我先考慮使用多程序了完成這項工作,分别讓它往一個文本中寫入資料,多開幾個程序。考慮到請求資料庫失敗,代碼報錯的問題,我選擇使用try函數跳過錯誤的請求失敗的文章,執行後我發現被跳過的文章太多,如果要重新爬取這些文章或減少損失,這是一件不容易的事情。

方法二——分為10段,同時開10個程式:

我需要爬取的文章從1~9331,被我分為了10段執行,并分别把文本寫入10個txt檔案,哪一個錯就重新執行哪一個,10個代碼同時執行。

第一個程式:第1~101篇,檔案夾:filename = 'G:攜程遊記之避暑01.txt'
第二個程式:第1001~201篇檔案夾:filename = 'G:攜程遊記之避暑02.txt'
第三個程式:第301~401篇檔案夾:filename = 'G:攜程遊記之避暑03.txt'
.........
第三個程式:第901~9332篇檔案夾:filename = 'G:攜程遊記之避暑10.txt'
           

10個程式分開同時執行:

攜程旅遊網與馬蜂窩遊客記錄爬取

儲存結果:

攜程旅遊網與馬蜂窩遊客記錄爬取

攜程問答爬取:

代碼片段其一:

import requests
from bs4 import BeautifulSoup
from lxml import etree
import time
start = time.time()#記錄開始時的時間
filename = "G:攜程問答之避暑3(1).txt"#儲存的文本命名及路徑
headers = {
     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'
}
allUrl = []#儲存擷取的連結
for page in range(1,26,1):
    index = 'https://you.ctrip.com/searchsite/asks/?query=避暑&isAnswered=&isRecommended=&publishDate=&PageNo=%s'%page
    print ("正在擷取:",index)
    indexHtml = requests.get(url=index,headers=headers).text
    etreeIndex = etree.HTML(indexHtml)
    liUrls = etreeIndex.xpath('/html/body/div[2]/div[2]/div[2]/div/div[1]/ul/li')
    for li in liUrls:
        href = li.xpath('./dl/dt/a/@href')[0]
        hrefUrl = 'https://you.ctrip.com'+href
        allUrl.append(hrefUrl)
urlNum = len(allUrl)
print ("一共找到%s篇文章需要爬取"%urlNum)
c = 0
for textUrl in allUrl:
    c = c + 1#記錄文章篇數
    if c in range(0,4676,10):
        time.sleep(50)#模拟暫停
    print ("正在爬取第%s篇文章,一共有4676篇"%c)
    textHtml = requests.get(url = textUrl,headers = headers).text
    textsoup = BeautifulSoup(textHtml,"html.parser")
    #提取作者筆記标題
    textTitle = textsoup.find(attrs={"class":"ask_title"}).get_text()
    print (textTitle)
    textTitle = str(textTitle)
    with open(filename,'a',encoding='utf-8') as f: # 如果filename不存在會自動建立, 'w'表示寫資料,寫之前會清空檔案中的原有資料!
        f.write(textTitle)
        f.close()
    #提取作者筆記
    titleQuestion = textsoup.find(attrs={"class":"ask_text"}).get_text()
    titleQuestion = str(titleQuestion)
    with open(filename,'a',encoding='utf-8') as f: # 如果filename不存在會自動建立, 'w'表示寫資料,寫之前會清空檔案中的原有資料!
        f.write(titleQuestion)
        f.close()
    #提取評論
    answerBoxs =  textsoup.find_all(attrs={"class":"answer_box cf"})
    for userAnswer in answerBoxs:
        answer = userAnswer.find(attrs={"class":"answer_text"}).get_text()
        answer = str(answer)
        with open(filename,'a',encoding='utf-8') as f: # 如果filename不存在會自動建立, 'w'表示寫資料,寫之前會清空檔案中的原有資料!
            f.write(answer+"\n")
            f.close()
end = time.time()#擷取目前時間
useTime = int(end-start)
useTime = useTime/60
print ("本次爬取所有文章一共使用%s分鐘"%useTime)
           

6個程式同時進行:

攜程旅遊網與馬蜂窩遊客記錄爬取

代碼運作結果:

攜程旅遊網與馬蜂窩遊客記錄爬取

文本儲存結果:

攜程旅遊網與馬蜂窩遊客記錄爬取

第四次項目交接

我看見彭老師在群裡給她的學生說,文本有空格和換行會影響資料分析,此刻她正在一個一個的删除文本空格和換行。為了節約時間,我就告訴她她文本放入word使用替換功能去掉多餘的空格和回車。

攜程旅遊網與馬蜂窩遊客記錄爬取

但是9千多篇文章還是太多了,她們的分析工具把電腦弄當機幾次後,重新決定隻要三年的資料,但是攜程網上又沒有專門篩選三年資料的地方,擔心不能實作。

攜程旅遊網與馬蜂窩遊客記錄爬取

後來我通過提取每個遊客的發表時間來提取文章,如果滿足2017,2018,2019年,就把它的連結追加在儲存連結的數組中,達篩到的目的。

for ettime in  ettimes:
        try:
            pTime = ettime.xpath('./dl/dd[2]/text()')[1]
            pTime = pTime.split("發表于")[1]
            pTime = pTime.split("-")[0]
            href = ettime.xpath('./dl/dt/a/@href')[0]
            hrefUrl = 'https://you.ctrip.com' + href
            if int(pTime) in [2017,2018,2019]:
                print ("符合條件的時間",pTime)
                print (hrefUrl)
                allUrl.append(hrefUrl)
        except:
            pass
           

第一頁,1~101頁查找結果:

攜程旅遊網與馬蜂窩遊客記錄爬取

源碼如下:

import requests,time
from lxml import etree
from bs4 import BeautifulSoup
start = time.time()
filename = 'G:攜程遊記之避暑201901.txt'
headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'
}
allUrl = []
for page in range(1,101,1):#1,932,1
    indexUrl = 'https://you.ctrip.com/searchsite/travels/?query=避暑&isAnswered=&isRecommended=&publishDate=&PageNo=%s'%page
    print ("正在擷取:",indexUrl)
    indexHtml = requests.get(url=indexUrl,headers=headers).text
    etreeIndex = etree.HTML(indexHtml)
    ettimes = etreeIndex.xpath('/html/body/div[2]/div[2]/div[2]/div/div[1]/ul/li')    
    for ettime in  ettimes:
        try:
            pTime = ettime.xpath('./dl/dd[2]/text()')[1]
            pTime = pTime.split("發表于")[1]
            pTime = pTime.split("-")[0]
            href = ettime.xpath('./dl/dt/a/@href')[0]
            hrefUrl = 'https://you.ctrip.com' + href
            if int(pTime) in [2017,2018,2019]:
                print ("符合條件的時間",pTime)
                print (hrefUrl)
                allUrl.append(hrefUrl)
        except:
            pass
urlNum = len(allUrl)
print ("一共找到%s篇文章需要爬取"%urlNum)
c = 0
for textUrl in allUrl:
    c = c + 1
    print ("正在爬取第%s篇文章,一共有%s篇"%(c,urlNum))
    try:
        html = requests.get(url = textUrl,headers=headers).text
        soup = BeautifulSoup(html, "html.parser")
        try:
            title = soup.find(attrs={"class": "title1"}).get_text().replace("\n","").replace(" ","")
        except:
            title = soup.find(attrs={"class": "ctd_head_left"}).get_text().replace("\n","").replace(" ","")
        title = str(title)
        print ("正在爬取:",title)
        t = soup.find(attrs={"class": "ctd_content"})
        txt = t.get_text().replace("\n","").replace(" ","")
        txt = str(txt)
        with open(filename,'a',encoding='utf-8') as f: # 如果filename不存在會自動建立, 'w'表示寫資料,寫之前會清空檔案中的原有資料!
            f.write(title)
            f.write(txt)
            f.close()
    except:
        pass
end = time.time()
useTime = int(end-start)
useTime = useTime/60
print ("該次爬取這%s文章共使用%s分鐘"%(urlNum,useTime))
           

第五次項目交接

三年的資料這樣存放不好使用分析,檔案還是太大了,需要把2017,2018,2019年的資料單獨存放,于是又對代碼做出了一些更改,完成了最後一次需求!

import requests,time
from lxml import etree
from bs4 import BeautifulSoup
start = time.time()
filename = 'G:攜程遊記之避暑201910.txt'
headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'
}
allUrl = []
c = 0
for page in range(901,932,1):#1,932,1
    indexUrl = 'https://you.ctrip.com/searchsite/travels/?query=避暑&isAnswered=&isRecommended=&publishDate=&PageNo=%s'%page
    print ("正在擷取:",indexUrl)
    indexHtml = requests.get(url=indexUrl,headers=headers).text
    etreeIndex = etree.HTML(indexHtml)
    ettimes = etreeIndex.xpath('/html/body/div[2]/div[2]/div[2]/div/div[1]/ul/li')
    for ettime in  ettimes:
        try:
            pTime = ettime.xpath('./dl/dd[2]/text()')[1]
            pTime = pTime.split("發表于")[1]
            pTime = pTime.split("-")[0]
            href = ettime.xpath('./dl/dt/a/@href')[0]
            hrefUrl = 'https://you.ctrip.com' + href
            if int(pTime) == 2019:
                print ("符合條件的時間",pTime)
                print (hrefUrl)
                allUrl.append(hrefUrl)
        except:
            pass
urlNum = len(allUrl)
print ("一共找到%s篇文章需要爬取"%urlNum)
for textUrl in allUrl:
    c = c + 1
    print ("正在爬取第%s篇文章,一共有%s篇"%(c,urlNum))
    try:
        html = requests.get(url = textUrl,headers=headers).text
        soup = BeautifulSoup(html, "html.parser")
        try:
            title = soup.find(attrs={"class": "title1"}).get_text().replace("\n","").replace(" ","")
        except:
            title = soup.find(attrs={"class": "ctd_head_left"}).get_text().replace("\n","").replace(" ","")
        title = str(title)
        print ("正在爬取:",title)
        t = soup.find(attrs={"class": "ctd_content"})
        txt = t.get_text().replace("\n","").replace(" ","")
        txt = str(txt)
        with open(filename,'a',encoding='utf-8') as f: # 如果filename不存在會自動建立, 'w'表示寫資料,寫之前會清空檔案中的原有資料!
            f.write(title)
            f.write(txt)
            f.close()
    except:
        pass
end = time.time()
useTime = int(end-start)
useTime = useTime/60
print ("該次爬取這%s文章共使用%s分鐘"%(urlNum,useTime))
           

運作結果截屏:

攜程旅遊網與馬蜂窩遊客記錄爬取

儲存文本結果:

攜程旅遊網與馬蜂窩遊客記錄爬取
攜程旅遊網與馬蜂窩遊客記錄爬取

很感謝這次的實戰機會,通過很多次的需求,讓我學會了很多處理資料的方法,提高自己的程式設計實戰能力,幫上一點小忙。