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表格進行理解
    client = pymongo.MongoClient('localhost',27017) # 將python與mongodb進行連接腐晾,'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方式對頁面進行解析
    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ù)器進行請求該商品詳情界面時會出現(xiàn)404 not found喇颁。我們可以通過status_code的方法對頁面進行判斷漏健。
    wb_data.status_code == 404 # 判斷商品是否已被賣出,賣出則返回TRUE无牵,沒有則返回FALSE

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

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

  • 多進程爬劝缒睢: 可以利用multiprocess庫中的pool函數(shù),進行多進程爬取碧库,這樣可以提高爬取的效率柜与。
    關(guān)于進程與線程:
    可以理解成多個人完成吃飯這個工作的效率:
    單線程單進程:只有一個餐桌,一個人在一個餐桌上吃飯嵌灰,每個人依次進行弄匕。
    單線程多進程:有多個餐桌,每個餐座上只有一個人在吃飯沽瞭。
    單進程多線程: 只有一個餐桌迁匠,一個餐桌上可以坐多個人。
    多進程多線程:多個餐座,一個餐桌上可以坐多個人驹溃。

  • 對項目進行監(jiān)測:
    我們可以設(shè)計一個檢測函數(shù)城丧,隔一段時間匯報所抓取信息的數(shù)量,對項目進程進行掌控豌鹤。
    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ù)進行抓取磺平。

    設(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)系作者
  • 序言:七十年代末俱诸,一起剝皮案震驚了整個濱河市菠劝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌睁搭,老刑警劉巖赶诊,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異园骆,居然都是意外死亡舔痪,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門锌唾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锄码,“玉大人,你說我怎么就攤上這事晌涕∽檀罚” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵余黎,是天一觀的道長重窟。 經(jīng)常有香客問我,道長惧财,這世上最難降的妖魔是什么巡扇? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮垮衷,結(jié)果婚禮上厅翔,老公的妹妹穿的比我還像新娘。我一直安慰自己帘靡,他們只是感情好知给,可當(dāng)我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著描姚,像睡著了一般涩赢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上轩勘,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天筒扒,我揣著相機與錄音,去河邊找鬼绊寻。 笑死花墩,一個胖子當(dāng)著我的面吹牛悬秉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播冰蘑,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼和泌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了祠肥?” 一聲冷哼從身側(cè)響起武氓,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎仇箱,沒想到半個月后县恕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡剂桥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年忠烛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片权逗。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡美尸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出旬迹,到底是詐尸還是另有隱情火惊,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布奔垦,位于F島的核電站屹耐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏椿猎。R本人自食惡果不足惜惶岭,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望犯眠。 院中可真熱鬧按灶,春花似錦、人聲如沸筐咧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽量蕊。三九已至铺罢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間残炮,已是汗流浹背韭赘。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留势就,地道東北人泉瞻。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓脉漏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親袖牙。 傳聞我的和親對象是個殘疾皇子侧巨,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容