• 小螞蟻站長吧-互聯網運營、增長黑客學習交流平臺

    您好,歡迎訪問小螞蟻站長吧!

    Python 獲取旅游景點信息及評論并作詞云、數據可

    2022-09-13 23:12分類:數據可視化 閱讀:

      今天將手被手教你使喚線程池爬取同程行旅之新景點信息及公論數據并做詞云、數據可視化?。?!帶你未卜先知各類城池之游玩新景點信息。

    各戶好,我是啃書君!

    正所謂:有朋自邊塞來,不亦樂乎?有哥兒們來找吾輩玩,是七件很快樂之碴兒,那么咱們要盡地主之誼,好好帶賓朋去玩耍!那么問題來了,何事早晚去哪背玩最好與否,哪背玩之地段最多也罷?

    今天將手被手教你用到線程池爬取同程行旅之新景點信息及輿情數據并做詞云、數據可視化?。?!帶你了然各條都會之游玩新景點信息。

    在從頭爬取數據之前,咱首先來知詳十下部線程。

    線程

    進程:進程是代碼在數據聯誼上之四次運行宣傳,是戰線拓展資源分配和調度之基本單位。

    線程:是輕計量級之進程,是程序執行之最小單元,是進程之十個執行路徑。

    二個進程中至少有二個線程,進程中之多個線程共享進程之資源。

    線程性命周期

    在創建多線程之前,俺們先來學學十下面線程性命周期,如底腳圖所示:

    由圖可知,線程得以分為伍個勢態——共建、就緒、運行、綠燈、末止。

    首先共建三個線程并開啟線程后線程上登就緒勢態,就緒勢態之線程不會馬上運行,要獲得CPU資源才會進來運行述態,在躋身運行述態后,線程有可能會失去CPU資源或者遇到懶覺、io操作(讀寫等操作)線程進來就緒勢態或者擁塞勢態,要等蠶眠、io操作壽終正寢或者重新獲得CPU資源后,才會上登運行述態,等到運行完后進來末止勢態。

    令人矚目:興建線程戰線是要求分配資源之,末止線程戰線是急需回收資源之,那么如何減去重建/末止線程之戰線開銷歟,這時咱倆得以創建線程池來重用線程,這樣就有何不可減掉戰線之開銷了。

    在創建線程池之前,咱先來習修如何創建多線程。

    創建多線程

    創建多線程得以分為肆步:

    1. 創建因變量;
    2. 創建線程;
    3. 啟動線程;
    4. 等待了卻;

    創建因變量

    為了方便演示,咱拿博客園之網頁做爬蟲因變量,具體代碼如下頭所示:

    import requests
    urls=[
    f'https://www.cnblogs.com/#p{page}'
    for page in range(1,50)
    ]
    def get_parse(url):
    response=requests.get(url)
    print(url,len(response.text))

    首先導出requests網絡央求庫,被咱所有之要爬取之URL封存在列表中,然后自概念因變量get_parse來發賜網絡懇請、打印央告之URL和響應之字符長。

    創建線程

    在上二步咱們創建了爬蟲因變量,接下部來將創建線程了,具體代碼如下部所示:

    import threading
    #多線程
    def multi_thread():
    threads=[]
    for url in urls:
    threads.append(
    threading.Thread(target=get_parse,args=(url,))
    )

    首先咱導出threading分組,自概念multi_thread因變量,再創建七個空列表threads來存放線程任務,通過threading.Thread()點子來創建線程。其中:

    • target為運行因變量;
    • args為運行因變量所需之參數。

    放在心上args中之參數要以元組之方式傳入,然后通過.append()解數被線程添加到threads空列表中。

    啟動線程

    線程已經創建好了,接下部來將啟動線程了,啟動線程很簡練,具體代碼如下邊所示:

    for thread in threads:
    thread.start()

    首先咱倆通過for循環往復被threads列表中之線程任務獲取下面來,通過.start()來啟動線程。

    等待收尾

    啟動線程后,接下邊來將等待線程收束,具體代碼如下部所示:

    for thread in threads:
    thread.join()

    和啟動線程九樣,先通過for循環往復被threads列表中之線程任務獲取下面來,再使喚.join()點子等待線程殆盡。

    多線程已經創建好了,接下邊來將測試十下邊多線程之速度如何,具體代碼如下頭所示:

    if __name__ == '__main__':
    t1=time.time()
    multi_thread()
    t2=time.time()
    print(t2-t1)

    運行結局如下部圖所示:

    多線程爬取50個博客園網頁只要1秒多,而且多線程之發給網絡呼吁之URL是隨機之。

    咱來測試十底下單線程之運行年光,具體代碼如下部所示:

    if __name__ == '__main__':
    t1=time.time()
    for i in urls:
    get_parse(i)
    t2=time.time()
    print(t2-t1)

    運行產物如下面圖所示:

    單線程爬取50個博客園網頁用了9秒多,單線程之發賜網絡懇求之URL是按順序之。

    在上表俺們說了,軍民共建線程戰線是要求分配資源之,末止線程戰線是急需回收資源之,為了打折扣戰線之開銷,咱有何不可創建線程池。

    線程池原理

    七個線程池由兩片段組成,如下邊圖所示:

    • 線程池:陰臉提早建好N個線程,那些都會被重申利用;
    • 任務隊列:當有新任務之時節,會被任務放在任務隊列中。

    當任務隊列背有任務時,線程池之線程會從任務隊列中取出任務并執行,執行完任務后,線程會執行底腳七個任務,直到沒有任務執行后,線程會回到線程池中型待任務。

    應用線程池得以操持突發性千千萬萬呈請或需求許許多多線程竣蕆任務(安排年光較短之任務)。

    好了,心明如鏡了線程池原理后,吾儕肇始創建線程池。

    線程池創建

    Python提供了ThreadPoolExecutor類來創建線程池,其語法如底下所示:

    ThreadPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=())

    其中:

    • max_workers:最大線程數;
    • thread_name_prefix:同意用戶控管由線程池創建之threading.Thread作業線程稱謂以方便調試;
    • initializer:是在每個業務者線程上馬處調用之十個可選可調用靶子;
    • initargs:傳送給初始化器之元組參數。

    在意:在啟動 max_workers 個事務線程之前也會重用悠閑之政工線程。

    在ThreadPoolExecutor類中提供了map()和submit()因變量來插入任務隊列。其中:

    map()因變量

    map()語法格式為:

    map(調用措施,參數隊列)

    具體示例如下面所示:

    import requestsimport concurrent.futuresimport timeurls=[    f'https://www.cnblogs.com/#p{page}'    for page in range(1,50)]def get_parse(url):    response=requests.get(url)    return response.textdef map_pool():    with concurrent.futures.ThreadPoolExecutor(max_workers=20) as pool:        htmls=pool.map(get_parse,urls)        htmls=list(zip(urls,htmls))        for url,html in htmls:            print(url,len(html))if __name__ == '__main__':    t1=time.time()    map_pool()    t2=time.time()    print(t2-t1)

    首先吾儕導出requests網絡乞求庫、concurrent.futures分組,被所有之URL放在urls列表中,然后自界說get_parse()法門來歸來網絡呈請回去之數據,再自界說map_pool()措施來創建代理池,其中代理池之最大max_workers為20,調用map()章程被網絡求見任務放在任務隊列中,在被回到之數據和URL合龍為元組,并放在htmls列表中。

    運行果如下部圖所示:

    堪好發現map()因變量回到之后果和傳入之參數順序是對應之。

    專注:當俺們直接在自界說點子get_parse()中打印下文時,打印后果是亂序之。

    submit()因變量

    submit()因變量語法格式如底下:

    submit(調用主意,參數)

    具體示例如下邊:

    def submit_pool():    with concurrent.futures.ThreadPoolExecutor(max_workers=20)as pool:        futuress=[pool.submit(get_parse,url)for url in urls]        futures=zip(urls,futuress)        for url,future in futures:            print(url,len(future.result()))

    運行后果如下部圖所示:

    放在心上:submit()因變量轉口下文需急需調用result()了局。

    好了,線程知識就學好此處了,接下面來肇端咱們之爬蟲。

    爬前分析

    首先俺們上登同程行旅之新景點網頁并拉開開發者器,如底腳圖所示:

    歷經搜求,吾儕發現各類新景點之根基信息(詳情頁URL、新景點id等)都存放在下邊圖之URL鏈接中,

    其URL鏈接為:

    https://www.ly.com/scenery/NewSearchList.aspx?&action=getlist&page=2&kw=&pid=6&cid=80&cyid=0&sort=&isnow=0&spType=&lbtypes=&IsNJL=0&classify=0&grade=&dctrack=1%CB%871629537670551030%CB%8720%CB%873%CB%872557287248299209%CB%870&iid=0.6901326566387387

    行經增刪繁就簡查操作,俺們得以被該URL簡化為:

    https://www.ly.com/scenery/NewSearchList.aspx?&action=getlist&page=1&pid=6&cid=80&cyid=0&isnow=0&IsNJL=0

    其中page為咱翻頁之緊要參數。

    啟封該URL鏈接,如下面圖所示:

    通過上皮之URL鏈接,吾輩堪好獲取到很多新景點之功底信息,隨機拉開二個新景點之詳情網頁并拉開開發者漸進式,駛過查找,公論數據存放在如下面圖之URL鏈接中,

    其URL鏈接如下面所示:

    https://www.ly.com/scenery/AjaxHelper/DianPingAjax.aspx?action=GetDianPingList&sid=12851&page=1&pageSize=10&labId=1&sort=0&iid=0.48901069375088

    其中:action、labId、iid、sort為常比量,sid是新景點之id,page主宰翻頁,pageSize是每頁獲取之數據計量。

    在上上步中,俺們知道新景點id之存放坐位,那么構造輿論數據之URL就很簡單易行了。

    實戰演練

    當年咱爬蟲步調是:

    1. 獲取新景點基本信息
    2. 獲取述評數據
    3. 創建MySQL數據庫
    4. 封存數據
    5. 創建線程池
    6. 數據分析

    獲取新景點基本信息

    首先咱先獲取新景點之名諱、id、價錢、特色、地址和等差,主要代碼如下邊所示:

    def get_parse(url):    response=requests.get(url,headers=headers)    Xpath=parsel.Selector(response.text)    data=Xpath.xpath('/html/body/div')    for i in data:        Scenery_data={            'title':i.xpath('./div/div[1]/div[1]/dl/dt/a/text()').extract_first(),            'sid':i.xpath('//div[@class="list_l"]/div/@sid').extract_first(),            'Grade':i.xpath('./div/div[1]/div[1]/dl/dd[1]/span/text()').extract_first(),       'Detailed_address':i.xpath('./div/div[1]/div[1]/dl/dd[2]/p/text()').extract_first().replace('地址:',''),            'characteristic':i.xpath('./div/div[1]/div[1]/dl/dd[3]/p/text()').extract_first(),            'price':i.xpath('./div/div[1]/div[2]/div[1]/span/b/text()').extract_first(),            'place':i.xpath('./div/div[1]/div[1]/dl/dd[2]/p/text()').extract_first().replace('地址:','')[6:8]        }

    首先自界說措施get_parse()來發給網絡伸手后使役parsel.Selector()法子來解析響應之文本數據,然后通過xpath來獲取數據。

    獲取輿論數據

    獲取新景點基本信息后,接下面來通過新景點基本信息中之sid來構造述評信息之URL鏈接,主要代碼如下面所示:

    def get_data(Scenery_data):    for i in range(1,3):        link = f'https://www.ly.com/scenery/AjaxHelper/DianPingAjax.aspx?action=GetDianPingList&sid={Scenery_data["sid"]}&page={i}&pageSize=100&labId=1&sort=0&iid=0.20105777381446832'        response=requests.get(link,headers=headers)        Json=response.json()        commtent_detailed=Json.get('dpList')        # 有輿論數據        if commtent_detailed!=None:            for i in commtent_detailed:                Comment_information={                    'dptitle':Scenery_data['title'],                    'dpContent':i.get('dpContent'),                    'dpDate':i.get('dpDate')[5:7],                    'lineAccess':i.get('lineAccess')                }        #沒有評說數據        elif commtent_detailed==None:            Comment_information={                'dptitle':Scenery_data['title'],                'dpContent':'沒有述評',                'dpDate':'沒有評語',                'lineAccess':'沒有評語'            }

    首先自概念點子get_data()并傳入剛才獲取之新景點功底信息數據,然后通過新景點根基信息之sid來構造述評數據之URL鏈接,當在構造輿論數據之URL時,急需設置pageSize和page這兩個變計計來獲取多條輿情和進展翻頁,構造URL鏈接后就發給網絡吁請。

    此處需求留意之是:有些新景點是沒有公論,故而俺們需求通過if語句來進展設置。

    創建MySQL數據庫

    那會兒咱被數據存放在MySQL數據庫中,鑒于數據較之多,據此我輩被數據分為兩種數據表,八種是新景點底蘊信息表,二種是新景點公論數據表,主要代碼如下面所示:

    #創建數據庫def create_db():    db=pymysql.connect(host=host,user=user,passwd=passwd,port=port)    cursor=db.cursor()    sql='create database if not exists commtent default character set utf8'    cursor.execute(sql)    db.close()    create_table()#創建新景點信息數據表def create_table():    db=pymysql.connect(host=host,user=user,passwd=passwd,port=port,db='commtent')    cursor=db.cursor()    sql = 'create table if not exists Scenic_spot_data (title varchar(255) not null, link varchar(255) not null,Grade varchar(255) not null, Detailed_address varchar(255) not null, characteristic varchar(255)not null, price int not null, place varchar(255) not null)'    cursor.execute(sql)    db.close()

    首先咱們調用pymysql.connect()辦法來接合數據庫,通過.cursor()獲取游標,再通過.execute()法門執行單條之sql語句,執行馬到成功后趕回受陰影響之行數,然后閉合數據庫連貫,最后調用自界說法子create_table()來創建新景點信息數據表。

    此地咱只給出了創建新景點信息數據表之代碼,坐蓋創建數據表只是sql這條語句稍微有線不同,任何都五樣,大伙兒堪好參考這代碼來創建各條新景點評語數據表。

    封存數據

    創建好數據庫差數據表后,接下邊來就要封存數據了,主要代碼如下面所示:

    首先咱調用pymysql.connect()措施來連通數據庫,通過.cursor()獲取游標,再通過.execute()章程執行單條之sql語句,執行中標后回去受暗影響之行數,役使了try-except語句,當封存之數據不得逞,就調用rollback()不二法門,撤消當前事務中所做之所有更改,并開釋此聯接目標當前下祭之所有數據庫鎖。

    #保留新景點數據到新景點數據表中def saving_scenery_data(srr):    db = pymysql.connect(host=host, user=user, password=passwd, port=port, db='commtent')    cursor = db.cursor()    sql = 'insert into Scenic_spot_data(title, link, Grade, Detailed_address, characteristic,price,place) values(%s,%s,%s,%s,%s,%s,%s)'    try:        cursor.execute(sql, srr)        db.commit()    except:        db.rollback()    db.close()

    放在心上:srr是傳入之新景點信息數據。

    創建線程池

    好了,單線程爬蟲已經寫好了,接底腳來將創建九個因變量來創建我輩之線程池,使單線程爬蟲變為多線程,主要代碼如底腳所示:

    urls = [    f'https://www.ly.com/scenery/NewSearchList.aspx?&action=getlist&page={i}&pid=6&cid=80&cyid=0&isnow=0&IsNJL=0'    for i in range(1, 6)]def multi_thread():    with concurrent.futures.ThreadPoolExecutor(max_workers=8)as pool:        h=pool.map(get_parse,urls)if __name__ == '__main__':    create_db()    multi_thread()

    創建線程池之代碼很簡約就二個with語句和調用map()藝術

    運行分曉如下頭圖所示:

    好了,數據已經獲取到了,接下面來將展開數據分析。

    數據可視化

    首先咱們來分析五下部各隊新景點彼其月度游玩之食指最多,這樣咱倆就不用挑心去游玩之會時不嘿。

    咱發現10月、2月、1月去廣州長隆飛鳥天府游玩之口占總體對比最多。分析完月度后,俺們來瞧瞅評述情狀如何:

    得以發現去好評占了絕大有些,得以說:去長隆飛鳥天府之國玩耍,去了都說好。瞧了述評情景,輿論情節有甚:

    好了,獲取旅游新景點信息及評說并做詞云、數據可視化就講到此地了。

    上一篇:手把手教你用 Power BI 實現四種可視化圖表

    下一篇:沒有了

    相關推薦
    ?

    關注我們

      小螞蟻站長吧-互聯網運營、增長黑客學習交流平臺
    返回頂部
    日韩在线精品视频a