Python爬蟲新手教程:微醫掛號網醫生資料抓取

程式設計師啟航發表於2019-07-20

1. 寫在前面

今天要抓取的一個網站叫做 微醫 網站,地址為   https://www.guahao.com   ,我們將通過python3爬蟲抓取這個網址,然後資料儲存到CSV裡面,為後面的一些分析類的教程做準備。本篇文章主要使用的庫為 pyppeteer     pyquery

首先找到 醫生列表頁

https://www.guahao.com/expert/all/全國/all/不限/p5

這個頁面顯示有   75952   條資料 ,實際測試中,翻頁到第38頁,資料就載入不出來了,目測後臺程式猿沒有把資料返回,不過為了學習,我們忍了。

Python爬蟲新手教程:微醫掛號網醫生資料抓取

2. 頁面URL

https://www.guahao.com/expert/all/全國/all/不限/p1
https://www.guahao.com/expert/all/全國/all/不限/p2
...
https://www.guahao.com/expert/all/全國/all/不限/p38

資料總過38頁,量不是很大,我們只需要隨便選擇一個庫抓取就行,這篇部落格,我找了一個冷門的庫
pyppeteer   在使用過程中,發現資料好少,很尷尬。而且官方的文件寫的也不好,有興趣的可以自行去看看。關於這個庫的安裝也在下面的網址中。

https://miyakogi.github.io/pyppeteer/index.html

最簡單的使用方法,在官方文件中也簡單的寫了一下,如下,可以把一個網頁直接儲存為一張圖片。

import asyncio
from pyppeteer import launch
async def main():
    browser = await launch()  # 執行一個無頭的瀏覽器
    page = await browser.newPage()  # 開啟一個選項卡
    await page.goto('http://www.baidu.com')  # 載入一個頁面
    await page.screenshot({'path': 'baidu.png'})  # 把網頁生成截圖
    await browser.close()
asyncio.get_event_loop().run_until_complete(main())  # 非同步

我整理了下面的一些參考程式碼,你可以 做一些參考。

browser = await launch(headless=False)  # 可以開啟瀏覽器
await page.click('#login_user')  # 點選一個按鈕
await page.type('#login_user', 'admin')  # 輸入內容
await page.click('#password')  
await page.type('#password', '123456')
await page.click('#login-submit')
await page.waitForNavigation()  
# 設定瀏覽器視窗大小
await page.setViewport({
    'width': 1350,
    'height': 850
})
content = await page.content()  # 獲取網頁內容
cookies = await page.cookies()  # 獲取網頁cookies

3. 爬取頁面

執行下面的程式碼,你就可以看到控制檯不斷的列印網頁的原始碼,只要獲取到原始碼,就可以進行後面的解析與儲存資料了。如果出現控制不輸出任何東西的情況,那麼請把下面的
await launch(headless=True) 修改為 await launch(headless=False)

import asyncio
from pyppeteer import launch
class DoctorSpider(object):
    async def main(self, num):
        try:
            browser = await launch(headless=True)
            page = await browser.newPage()
            print(f"正在爬取第 {num} 頁面")
            await page.goto("https://www.guahao.com/expert/all/全國/all/不限/p{}".format(num))
            content = await page.content()
            print(content)
        except Exception as e:
            print(e.args)
        finally:
            num += 1
            await browser.close()
            await self.main(num)
    def run(self):
        loop = asyncio.get_event_loop()
        asyncio.get_event_loop().run_until_complete(self.main(1))
if __name__ == '__main__':
    doctor = DoctorSpider()
    doctor.run()
Python資源分享qun 784758214 ,內有安裝包,PDF,學習視訊,這裡是Python學習者的聚集地,零基礎,進階,都歡迎

4. 解析資料

解析資料採用的是pyquery ,這個庫在之前的部落格中有過使用,直接應用到案例中即可。最終產生的資料通過 pandas 儲存到CSV檔案中。

import asyncio
from pyppeteer import launch
from pyquery import PyQuery as pq
import pandas as pd  # 儲存csv檔案
class DoctorSpider(object):
    def __init__(self):
        self._data = list()
    async def main(self,num):
        try:
            browser = await launch(headless=True)
            page = await browser.newPage()
            print(f"正在爬取第 {num} 頁面")
            await page.goto("https://www.guahao.com/expert/all/全國/all/不限/p{}".format(num))
            content = await page.content()
            self.parse_html(content)
            print("正在儲存資料....")
            data = pd.DataFrame(self._data)
            data.to_csv("微醫資料.csv", encoding='utf_8_sig')
        except Exception as e:
            print(e.args)
        finally:
            num+=1
            await browser.close()
            await self.main(num)
    def parse_html(self,content):
        doc = pq(content)
        items = doc(".g-doctor-item").items()
        for item in items:
            #doctor_name = item.find(".seo-anchor-text").text()
            name_level = item.find(".g-doc-baseinfo>dl>dt").text() # 姓名和級別
            department = item.find(".g-doc-baseinfo>dl>dd>p:eq(0)").text() # 科室
            address = item.find(".g-doc-baseinfo>dl>dd>p:eq(1)").text()  # 醫院地址
            star = item.find(".star-count em").text()  # 評分
            inquisition = item.find(".star-count i").text() # 問診量
            expert_team = item.find(".expert-team").text()  # 專家團隊
            service_price_img = item.find(".service-name:eq(0)>.fee").text()
            service_price_video = item.find(".service-name:eq(1)>.fee").text()
            one_data = {
                "name": name_level.split(" ")[0],
                "level": name_level.split(" ")[1],
                "department": department,
                "address": address,
                "star": star,
                "inquisition": inquisition,
                "expert_team": expert_team,
                "service_price_img": service_price_img,
                "service_price_video": service_price_video
            }
            self._data.append(one_data)
    def run(self):
        loop = asyncio.get_event_loop()
        asyncio.get_event_loop().run_until_complete(self.main(1))
if __name__ == '__main__':
    doctor = DoctorSpider()
    doctor.run()
Python資源分享qun 784758214 ,內有安裝包,PDF,學習視訊,這裡是Python學習者的聚集地,零基礎,進階,都歡迎

總結一下,這個庫不怎麼好用,可能之前沒有細細的研究過,感覺一般,你可以在多嘗試一下,看一下是否可以把整體的效率提高上去。

資料清單:

Python爬蟲新手教程:微醫掛號網醫生資料抓取


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913713/viewspace-2651231/,如需轉載,請註明出處,否則將追究法律責任。

相關文章