Python 爬蟲實戰(zhàn)計劃:第一周實戰(zhàn)作業(yè)

要求:
1. 爬取58同城轉(zhuǎn)轉(zhuǎn)二手交易平臺商品信息 http://bj.58.com/pbdn/0/
2. 爬取每一頁商品的所有商品鏈接旷痕,爬取前十頁
3. 爬取每一件商品的詳細信息:類目碳锈,標題,價格欺抗,區(qū)域
分析:
1. 每一頁商品的鏈接格式都相同均為 :http://bj.58.com/pbdn/0/pn{}/售碳,
由此在{}內(nèi)填充1-10,即可得到前10頁的商品html頁面地址。
2.每一頁中每一條商品的詳情頁面均在
“div#infolist > div[class=infocon] > table.tbimg tbody > tr > td.t > a” 路徑下
3. 商品詳情頁:
類目:"div#nav > div.breadCrumb.f12 span a"
標題:"h1.info_titile"
價格:"span.price_now i"
區(qū)域:"div.palce_li span > i"
4. 避免程序的中斷绞呈,再次重啟后數(shù)據(jù)的重復(fù)下載贸人,構(gòu)造了一個緩存模塊:
1.設(shè)置緩存保質(zhì)期為1天,過期則刪除緩存
2. 對未在緩存內(nèi)的頁面進行下載佃声。
3.將頁面url作為唯一標示艺智,保存在緩存內(nèi)
4.將url轉(zhuǎn)換為MD5碼保存在磁盤中,
因為windows磁盤文件命名系統(tǒng)對特殊的字符有限制圾亏,而且最長不能超過255個字符十拣,
相對于url來說,可能包含一些非法的文件命名字符志鹃,所以轉(zhuǎn)換為MD5來存儲夭问,簡單粗暴
5. 將爬取的商品信息保存到CSV文件內(nèi)。如下:

image.png

具體代碼如下:

#coding=utf-8
"""爬取五八同城 轉(zhuǎn)轉(zhuǎn)二手交易平臺商品信息"""
import os
import csv
import time
import shutil
import datetime
import hashlib
import requests
from bs4 import BeautifulSoup

class Cache(object):
    """緩存類曹铃,用于處理緩存文件
        緩存保質(zhì)期為1天缰趋,失效則刪除緩存文件"""
    def __init__(self,cache_name='cache'):
        """如果緩存文件夾不存在,則新建緩存文件夾"""
        if not os.path.exists(cache_name):
            os.mkdir(cache_name)
            #建立一個time文件,用來儲存上次啟動爬蟲的時間
            #本次啟動時間與上次啟動時間的間隔大于1天埠胖,則清除所有緩存
            with open(cache_name+'/time','w') as f:
                #獲得當(dāng)前系統(tǒng)時間糠溜,并按照時間格式轉(zhuǎn)換為字符串格式
                time_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                f.write(time_str)

        with open(cache_name + '/time', 'r') as f:
            time_str = f.read()
            time_date = datetime.datetime.strptime(time_str,'%Y-%m-%d %H:%M:%S')
            if datetime.datetime.now() - time_date > datetime.timedelta(days=1):
                #shutil是一個高級的文件操作模塊
                #rmtree 刪除目錄下的所有文件及文件夾,包括子文件夾內(nèi)的所有文件及文件夾直撤,遞歸刪除
                #os模塊
                #os.remove(name)只能刪除文件非竿,不能刪除文件夾(目錄)
                #os.rmdir(name)只能刪除空文件夾(目錄),非空則報錯
                #os.removedirs()刪除空文件夾(目錄)及空的子文件夾(目錄),非空則報錯谋竖。遞歸刪除
                shutil.rmtree(cache_name)
                print '緩存保存日期大于1天红柱,已過期,從新下載數(shù)據(jù)'
            else:
                print '緩存正常 非過期'
        self.cache_name = cache_name

    def __url_md5(self,url):
        """獲得url對應(yīng)的md5碼"""
        # 獲得url的MD5碼
        # 因為windows磁盤文件命名系統(tǒng)對特殊的字符有限制蓖乘,而且最長不能超過255個字符
        # 相對于url來說锤悄,可能包含一些非法的文件命名字符,所以轉(zhuǎn)換為MD5來存儲嘉抒,簡單粗暴
        md5 = hashlib.md5()
        md5.update(url)
        return md5.hexdigest()

    def is_cache(self,url):
        """判斷緩存是否存在
            返回 True 表示存在零聚,F(xiàn)alse表示不存在"""
        cache_list = os.listdir(self.cache_name)  # 獲得緩存文件名列表
        # 獲得url的MD5碼
        md5 = self.__url_md5(url)
        if md5 in cache_list:
            print '已經(jīng)緩存該 {} 網(wǎng)頁'.format(url)
            return True
        return False

    def save_cache(self,url):
        """保存url到緩存"""
        old_path = os.getcwd()  # 獲得當(dāng)前工作目錄路徑
        os.chdir(self.cache_name)  # 改變工作目錄為緩存文件
        #print '切換后--',os.getcwd()
        with open(self.__url_md5(url), 'w'):
            pass
        print '緩存不存在,緩存 {} 網(wǎng)頁'.format(url)
        os.chdir(old_path)  # 切換到原始目錄

def get_html(url):
    """獲得網(wǎng)頁源碼"""
    time.sleep(1)  # 延遲1秒
    headers = {
        'User-Agent': ('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)'
                       'Chrome/54.0.2840.87 Safari/537.36')
    }
    html = requests.get(url, headers=headers).text
    return html

def get_product_list(url):
    """獲得當(dāng)前頁所有商品的鏈接
       返回一個list"""
    html = get_html(url)
    soup = BeautifulSoup(html, 'lxml')
    # div[class=infocom] 表示選擇 <div class = 'infocom'>xxxx</div>的標簽
    #    <div class = 'infocom jzcon'>xxxx</div> 則不會被選擇
    # 如果需要選擇 class='infocom jzcon'
    #   可以使用 'div.infocom.jzcon'
    # 切記:'div.infocom' 是只要 class屬性里包含 infocm 就會被查詢到
    #   例如:<div class = 'infocom'>xxxx</div> <div class = 'infocom jzcon'>xxxx</div>
    #    'div.infocom' 會返回查詢到的 兩個標簽信息 而不是一個
    #    想要得到唯一的<div class = 'infocom'>些侍,
    #    則需要 'div[class=infocom']
    products = soup.select('div#infolist > div[class=infocon] > table.tbimg tbody > tr > td.t > a')
    product_list = [product.get('href') for product in products]
    print '當(dāng)前頁 {} 有 {} 個商品'.format(url,len(product_list))
    return product_list

def product_detailed_info(url):
    """獲得商品的詳細信息
       商品類目隶症,商品標題,商品價格岗宣,商品區(qū)域
       """
    html = get_html(url)
    soup = BeautifulSoup(html, 'lxml')
    product_type = soup.select('div#nav > div.breadCrumb.f12 span a')[-1].get_text().strip()
    product_title = soup.select('h1.info_titile')[0].get_text().strip()
    product_price = soup.select('span.price_now i')[0].get_text().strip()
    product_area = soup.select('div.palce_li span > i')[0].get_text()

    product_dict = {}
    product_dict['type'] = product_type.encode('utf-8')
    product_dict['title'] = product_title.encode('utf-8')
    product_dict['price'] = product_price
    product_dict['area'] = product_area.encode('utf-8')

    #爬取一個商品詳細信息蚂会,保存一個,避免程序的以外中斷導(dǎo)致數(shù)據(jù)的丟失
    save_product_info(product_dict,'product.csv')
    print '保存商品信息到文件 {}'.format(url)

def save_product_info(info,file_name):
    """保存商品信息到指定文件內(nèi)"""
    fieles = ['price','area','type','title']
    if not os.path.exists(file_name):
        with open(file_name, 'wb') as f:
            writer = csv.DictWriter(f, fieldnames=fieles)
            writer.writerow(dict(zip(fieles, fieles)))
    with open(file_name,'ab') as f:
        writer = csv.DictWriter(f, fieldnames=fieles)
        writer.writerow(info)

def start():
    """啟動爬蟲"""
    # 獲得前十頁的url
    base_url = 'http://bj.58.com/pbdn/0/pn{}/'
    urls = [base_url.format(page) for page in range(1, 11)]

    # 獲得每一頁中的商品鏈接
    product_url_set = set()
    for url in urls:
        product_url_set.update(get_product_list(url))
    print '總共 {} 商品'.format(len(product_url_set))

    #獲得每件商品的詳細信息
    #并將已下載過的url保存到緩存中
    count = 0
    cache = Cache() #緩存
    for product_url in product_url_set:
        if not cache.is_cache(product_url):
            product_detailed_info(product_url)
            cache.save_cache(product_url)
            count += 1
    print '本次保存 {} 件商品'.format(count)

if __name__ == '__main__':
    #啟動爬蟲
    start()

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末耗式,一起剝皮案震驚了整個濱河市胁住,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌刊咳,老刑警劉巖彪见,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異娱挨,居然都是意外死亡企巢,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進店門让蕾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人或听,你說我怎么就攤上這事探孝。” “怎么了誉裆?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵顿颅,是天一觀的道長。 經(jīng)常有香客問我足丢,道長粱腻,這世上最難降的妖魔是什么庇配? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮绍些,結(jié)果婚禮上捞慌,老公的妹妹穿的比我還像新娘。我一直安慰自己柬批,他們只是感情好啸澡,可當(dāng)我...
    茶點故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著氮帐,像睡著了一般嗅虏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上上沐,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天皮服,我揣著相機與錄音,去河邊找鬼参咙。 笑死龄广,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的昂勒。 我是一名探鬼主播蜀细,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼戈盈!你這毒婦竟也來了奠衔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤塘娶,失蹤者是張志新(化名)和其女友劉穎归斤,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體刁岸,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡脏里,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了虹曙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迫横。...
    茶點故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖酝碳,靈堂內(nèi)的尸體忽然破棺而出矾踱,到底是詐尸還是另有隱情,我是刑警寧澤疏哗,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布呛讲,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏贝搁。R本人自食惡果不足惜吗氏,卻給世界環(huán)境...
    茶點故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望雷逆。 院中可真熱鬧弦讽,春花似錦、人聲如沸关面。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽等太。三九已至捂齐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缩抡,已是汗流浹背奠宜。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瞻想,地道東北人压真。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像蘑险,于是被迫代替她去往敵國和親滴肿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,654評論 2 354

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