Python爬蟲學(xué)習(xí)-爬取大規(guī)模數(shù)據(jù)(10w級)

編譯環(huán)境:python v3.5.0, mac osx 10.11.4
<big>python爬蟲基礎(chǔ)知識: Python爬蟲學(xué)習(xí)-基礎(chǔ)爬取</big>

了解數(shù)據(jù)庫 MongoDB

  • 數(shù)據(jù)庫是儲存數(shù)據(jù)的地方,可以將如下的字典結(jié)構(gòu)插入到MongoDB的存儲單元中。
    data = {
    'name':peter
    'id':123
    ...
    } # 需存儲的文件
  • 數(shù)據(jù)庫的構(gòu)成:可以將其類比于excel表格進(jìn)行理解
    client = pymongo.MongoClient('localhost',27017) # 將python與mongodb進(jìn)行連接,'localhost'表示本地環(huán)境, 207017是端口號
    walden = client['walden'] # 創(chuàng)建一個庫文件
    以上代碼可以類似于創(chuàng)建一個excel文件,文件名為walden



    sheet_tab = walden['sheet_tab'] # 在庫文件中建立一個頁面名叫 sheet_tab
    以上代碼可以類似于創(chuàng)建excel文件中的一個表單


  • 數(shù)據(jù)庫的基本操作:
    1. 向頁邊中插入數(shù)據(jù):sheet_tab.insert_one(data)
      其中data為python中的字典結(jié)構(gòu),可有如下代碼生成:
      path = './walden.txt' # 輸入數(shù)據(jù)的路徑,為讀取數(shù)據(jù)做準(zhǔn)備
      with open(path,'r') as f: # 打開文件,為只讀模式
      lines = f.readlines()
      for index,line in enumerate(lines): # 逐個生成字典元素
      data = {
      'index':index,
      'line' :line,
      'words':len(line.split())
      }
      sheet_tab.insert_one(data) # 將字典元素插入庫文件頁面中
  1. 篩選數(shù)據(jù)庫中的數(shù)據(jù)(基礎(chǔ)篩選)
    sheet_tab.find({'words':{'$lt':5}} # 選擇字典中關(guān)鍵字words對應(yīng)值小于5的所有字典元素
    # $lt/$lte/$gt/$gte/$ne,依次等價于</<=/>/>=/!=。(l表示less g表示greater e表示equal n表示not )

基礎(chǔ)實戰(zhàn)(篩選房源)

篩選小豬短租網(wǎng)站前三頁信息儲存到MongoDB中,篩選出價格大于等于500元房源,并打印出來。房源信息具體要求如下:

  • <big>實戰(zhàn)源碼</big> (下載地址xiaozhu.py
    # -- coding: utf-8 --
    import requests, time, pymongo
    from bs4 import BeautifulSoup
    def gender_info(soup): # 獲取性別信息
    gender = 'female' if soup.find_all('div','div.member_ico1') else 'male'
    return gender
    def get_info(url): # 獲取所需的房源信息
    wb_data = requests.get(url) # 向服務(wù)器請求頁面
    wb_data.encoding ='utf-8' # 標(biāo)明編碼為utf-8,以免出現(xiàn)解碼錯誤
    soup = BeautifulSoup(wb_data.text,'lxml') # 以lxml方式對頁面進(jìn)行解析
    title = soup.select('h4 em')[0].text
    address = soup.select('span.pr5')[0].text
    price = int(soup.select('div.day_l span')[0].text)
    img = soup.select('#curBigImage')[0].get('src')
    hostPic = soup.select('#floatRightBox > div.js_box.clearfix > div.member_pic > a > img')[0].get('src')
    hostName = soup.select('#floatRightBox > div.js_box.clearfix > div.w_240 > h6 > a')[0].text
    hostGender = gender_info(soup)
    data = {
    'title' : title,
    'address': address,
    'price' : price,
    'img' :img,
    'hostPic' : hostPic,
    'hostName' : hostName,
    'hostGender' : hostGender
    }
    print('get_info Done')
    return data
    def get_list_url(pageURL): # 獲取頁面中所有詳細(xì)房源的url
    listUrl = []
    wb_data = requests.get(pageURL)
    wb_data.encoding = 'utf-8'
    soup = BeautifulSoup(wb_data.text,'lxml')
    pageList = soup.select('div.result_btm_con.lodgeunitname')
    for i in pageList:
    listUrl.append(i.get('detailurl'))
    print('get_list_url Done')
    return listUrl
    def get_info_by_page(startPage, endPage, baseURL,database): # 獲取整個頁面的信息
    for i in range(startPage,endPage+1):
    url = baseURL.format(i)
    listUrl = get_list_url(url)
    for j in listUrl:
    time.sleep(4)
    dataInfo = get_info(j) # 獲取每個頁面的信息
    database.insert_one(dataInfo) # 將信息插入到指定的頁面中
    print('input to database Done')
    client = pymongo.MongoClient('localhost',27017) # 連接mongodb
    xiaozhu = client['xiaozhu'] # 創(chuàng)建一個名叫xiaozhu的庫文件
    home_info = xiaozhu['home_info'] # 創(chuàng)建一個home_info的頁面
    pageBaseUrl = 'http://bj.xiaozhu.com/search-duanzufang-p{}-0/' # 構(gòu)造共同url連接
    get_info_by_page(1,3,pageBaseUrl,home_info) # 調(diào)用函數(shù)爬取信息并將信息儲存到mongodb中
    for info in home_info.find({'price':{'$gte':500}}): # 打印大于等于500的房源信息
    print(info)
  • <big>結(jié)果展示</big>
    mongoDB中的儲存結(jié)果(部分截圖)
    價格大于等于500的房源信息(部分截圖)

爬取工作分析流程

<big>1. </big>觀察頁面特征,保證爬蟲程序的通用性,即:發(fā)現(xiàn)邊界條件和局限性。
例:爬取趕集網(wǎng)-北京二手市場的所有類目中屬于<big>個人</big>的商品信息。

  • 觀察的到頁面(url)變動的信息


  • 發(fā)現(xiàn)頁面變動邊界條件
    1. 當(dāng)把頁面設(shè)定到150頁時,我們發(fā)現(xiàn)返回的頁面是任意四件商品的信息。因此,我們要據(jù)此,判斷我們所爬取的頁面是否已經(jīng)到頭。避免重復(fù)的信息加入到我們的數(shù)據(jù)庫中。
    2. 并且通過觀察發(fā)現(xiàn)網(wǎng)站這一返回操作,我們發(fā)現(xiàn)正常頁面中有列表鏈接可以點擊,而由于頁面超出范圍返回的隨機商品信息頁面沒有。
    3. 因此我們可以用BeautifulSoup庫中的find方法實現(xiàn)這個操作。
      soup.find('ul', 'pageLink') #找到返回TRUE,沒有返回FALSE
  • 一般這種交易網(wǎng)站,當(dāng)商品賣出后,商品有關(guān)信息頁面將會被刪除,所以我們爬取的過程中,可能將有商品被賣出,當(dāng)我們向服務(wù)器進(jìn)行請求該商品詳情界面時會出現(xiàn)404 not found。我們可以通過status_code的方法對頁面進(jìn)行判斷。
    wb_data.status_code == 404 # 判斷商品是否已被賣出,賣出則返回TRUE,沒有則返回FALSE

<big>2. </big>設(shè)計工作流程,保證輸出效率和穩(wěn)定性。

  • 分步進(jìn)行:先獲取channel_list(所有頻道分類的URL),保證爬取的穩(wěn)定性。若是爬取類目信息,與爬取商品信息同步進(jìn)行的話,當(dāng)程序出現(xiàn)錯誤時,我們則什么信息也不能得到。所以分步進(jìn)行可以降低風(fēng)險。(圖中分類項目下的所有商品詳情鏈接)

  • 多進(jìn)程爬?。?/strong> 可以利用multiprocess庫中的pool函數(shù),進(jìn)行多進(jìn)程爬取,這樣可以提高爬取的效率。
    關(guān)于進(jìn)程與線程:
    可以理解成多個人完成吃飯這個工作的效率:
    單線程單進(jìn)程:只有一個餐桌,一個人在一個餐桌上吃飯,每個人依次進(jìn)行。
    單線程多進(jìn)程:有多個餐桌,每個餐座上只有一個人在吃飯。
    單進(jìn)程多線程: 只有一個餐桌,一個餐桌上可以坐多個人。
    多進(jìn)程多線程:多個餐座,一個餐桌上可以坐多個人。

  • 對項目進(jìn)行監(jiān)測:
    我們可以設(shè)計一個檢測函數(shù),隔一段時間匯報所抓取信息的數(shù)量,對項目進(jìn)程進(jìn)行掌控。
    import timeframe page_parsing
    import url_list
    while True:
    print(url_list.find().count())
    time.sleep(5)

  • 設(shè)計斷點續(xù)傳程序:
    由于在我們抓取的過程中可能會遇到網(wǎng)絡(luò)問題,導(dǎo)致程序終止,而我們不希望重新開始抓取,而是在中斷后的地方繼續(xù)進(jìn)行抓取。

    設(shè)計思路如下:

    1. 數(shù)據(jù)庫中建立兩個頁面存放詳情商品鏈接(從這一點也可以看出分步抓取的重要性)。一個存放需要抓取的(url_list1)一個存放已經(jīng)抓取網(wǎng)商品信息的 (url_list2)。
  1. 當(dāng)中斷后繼續(xù)抓取時,url_list1-url_list2就是剩下帶抓取的商品信息頁面。
    db_urls = [item['url'] for item in url_list.find()] # 用列表解析式裝入所有要爬取的鏈接
    index_urls = [item['url'] for item in item_info.find()] # 所引出詳情信息數(shù)據(jù)庫中所有的現(xiàn)存的 url 字段
    x = set(db_urls) # 轉(zhuǎn)換成集合的數(shù)據(jù)結(jié)構(gòu)
    y = set(index_urls)rest_of_urls = x-y # 剩下的url

爬取結(jié)果以及源碼(按設(shè)計步驟展示)

**All source code **: JacobKam-GitHub

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容