我的第一個爬蟲小程序——到底有多少人半途而廢?

猜想:看廖雪峰python教程的時候我就在想盅粪,這上百篇的教程钓葫,到底有多少人能夠堅持到最后呢?然后就想到學(xué)完一定要把這種半途而廢的現(xiàn)象赤裸裸地展現(xiàn)出來票顾,哈哈哈础浮。結(jié)果請看圖片,不言自明奠骄,下降趨勢明顯豆同。

參考資料

  1. 這是一個人寫的爬蟲入門教程,我覺得很適合入門
  2. Python 爬蟲:把廖雪峰教程轉(zhuǎn)換成 PDF 電子書
  3. 《python編程:從入門到實踐》第15章開始有講怎么畫圖

步驟方法:
1含鳞、請詳細(xì)耐心看完以上的幾篇入門文章之后
2影锈、所有教程的鏈接在第一篇教程的左邊,我們需要獲取所有的鏈接蝉绷,這個在參考文章2里面有說到鸭廷,請查看。


3熔吗、閱讀量按F12辆床,然后Ctrl+F,輸入閱讀量的數(shù)字磁滚,發(fā)現(xiàn)這個數(shù)字在網(wǎng)頁中的位置佛吓,于是我們知道這在x-wiki-info這個class中,通過beautifulsoup的查找方法垂攘,我們可以得到這個標(biāo)簽维雇,之后就很容易得到這個數(shù)字了

4、最后是把數(shù)字以折線圖的形式畫出來晒他,請看參考文檔3
5吱型、之后學(xué)了異步之后改為異步請求多個網(wǎng)頁,看看效果怎么樣陨仅,見代碼2
40個網(wǎng)站在相同的網(wǎng)速之下異步和同步所花時間之比為2:3
6津滞、上個步驟容易導(dǎo)致下載的網(wǎng)速過快,然后就被封掉了灼伤,從這篇文章的最后教我們用協(xié)程的信號量來控制協(xié)程的個數(shù)触徐,這樣子就可以避免上述問題了。見代碼3

  • 代碼1:同步執(zhí)行源碼:
import requests
from bs4 import BeautifulSoup
import matplotlib.pyplot as plt
import time
import os

START_URL = 'https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000'
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'

# 時間測量的裝飾器
def timing(f):
    def wrap(*args):
        time1_s = time.time()
        ret = f(*args)
        time2_s = time.time()
        print('%s function took %0.3f s' % (f.__name__, (time2_s-time1_s)))
        return ret
    return wrap

@timing
def get_all_urls():
    # 要模擬瀏覽器登陸
    headers = {'User-Agent': USER_AGENT}
    response = requests.get(START_URL,headers=headers)
    # print(response.content.decode())

    bsobj = BeautifulSoup(response.content, 'lxml')
    urls = bsobj.find('ul',{'class':'uk-nav uk-nav-side','style':'margin-right:-15px;'}).find_all('li')
    return urls

@timing
def ReadNum(url):
    # print(url)
    # 要模擬瀏覽器登陸
    headers = {'User-Agent': USER_AGENT}
    response = requests.get(url, headers=headers)
    # print(response.content.decode())
    soup = BeautifulSoup(response.content, 'lxml')
    ReadInfo = soup.find(class_='x-wiki-info')
    num = int(ReadInfo.span.string.split(':')[1])
    return num
    # print(num)


def main():
    all_readInfo = []
    urls = get_all_urls()

    # ReadNum('https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000')

    urls_num = len(urls)
    for i,url in enumerate(urls):
        # if i <= 5:
        num = ReadNum('https://www.liaoxuefeng.com' + urls[i].a['href'])
        if num is not None:
            all_readInfo.append(num)
        print('還剩下',urls_num - i)
        # else:
        #     break

    plt.plot(all_readInfo)
    plt.show()

代碼2:異步執(zhí)行源碼狐赡,python版本要大于3.4

import requests
from bs4 import BeautifulSoup
import matplotlib.pyplot as plt
import time
import aiohttp
import asyncio

START_URL = 'https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000'
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
READING_INFO = []
NUM_LEFT = 0

# 時間測量的裝飾器
def timing(f):
    def wrap(*args):
        time1_s = time.time()
        ret = f(*args)
        time2_s = time.time()
        print('%s function took %0.3f s' % (f.__name__, (time2_s-time1_s)))
        return ret
    return wrap

@timing
def get_all_urls():
    # 要模擬瀏覽器登陸
    headers = {'User-Agent': USER_AGENT}
    response = requests.get(START_URL,headers=headers)
    # print(response.content.decode())

    bsobj = BeautifulSoup(response.content, 'html.parser')
    tags = bsobj.find('ul',{'class':'uk-nav uk-nav-side','style':'margin-right:-15px;'}).find_all('a')

    urls = []
    for tag in tags:
        urls.append('https://www.liaoxuefeng.com' + tag['href'])
    # print(urls)
    return urls


def read_num(url):
    # print(url)
    # 要模擬瀏覽器登陸
    headers = {'User-Agent': USER_AGENT}
    response = requests.get(url, headers=headers)
    # print(response.content.decode())
    soup = BeautifulSoup(response.content, 'html.parser')
    ReadInfo = soup.find(class_='x-wiki-info')
    num = int(ReadInfo.span.string.split(':')[1])
    return num
    # print(num)


async def read_num_asyncio(url,index):
    # 要模擬瀏覽器登陸
    headers = {'User-Agent': USER_AGENT}
    async with aiohttp.ClientSession() as client:
        async with client.get(url, headers=headers) as resp:
            assert resp.status == 200
            txt = await resp.text()

    # async with aiohttp.get(url, headers=headers) as resp:
    #     assert resp.status == 200
    #     txt = await resp.text()
    #     # print(txt)

    soup = BeautifulSoup(txt,'html.parser')
    read_info = soup.find(class_='x-wiki-info')
    num = int(read_info.span.string.split(':')[1])
    # print(num)
    global NUM_LEFT,READING_INFO
    READING_INFO[index] = num
    NUM_LEFT += 1
    print(NUM_LEFT)
    # return num


# 異步方法讀取100+個教程網(wǎng)頁然后提取出閱讀量
def asyncio_get_reading_num(urls):
    loop = asyncio.get_event_loop()
    tasks = [read_num_asyncio(url,index) for index,url in enumerate(urls) if index < 20]
    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()


@timing
def main():
    urls = get_all_urls()
    print(len(urls))


    global READING_INFO
    READING_INFO = [0] * len(urls)

    asyncio_get_reading_num(urls)


    # all_readInfo = []
    # urls_num = len(urls)
    # for i,url in enumerate(urls):
    #     if i <= 40:
    #         num = read_num(url)
    #         if num is not None:
    #             all_readInfo.append(num)
    #         print(i)
    #     else:
    #         break

    # plt.plot(READING_INFO)
    # plt.show()

if __name__ == '__main__':
    main()

  • 代碼3:用協(xié)程信號量來限制協(xié)程運行個數(shù)
import requests
from bs4 import BeautifulSoup
import matplotlib.pyplot as plt
import time
import aiohttp
import asyncio

START_URL = 'https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000'
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
READING_INFO = []
NUM_LEFT = 0

# 時間測量的裝飾器
def timing(f):
    def wrap(*args):
        time1_s = time.time()
        ret = f(*args)
        time2_s = time.time()
        print('%s function took %0.3f s' % (f.__name__, (time2_s-time1_s)))
        return ret
    return wrap

@timing
def get_all_urls():
    # 要模擬瀏覽器登陸
    headers = {'User-Agent': USER_AGENT}
    response = requests.get(START_URL,headers=headers)
    # print(response.content.decode())

    bsobj = BeautifulSoup(response.content, 'html.parser')
    tags = bsobj.find('ul',{'class':'uk-nav uk-nav-side','style':'margin-right:-15px;'}).find_all('a')

    urls = []
    for tag in tags:
        urls.append('https://www.liaoxuefeng.com' + tag['href'])
    # print(urls)
    return urls


def read_num(url):
    # print(url)
    # 要模擬瀏覽器登陸
    headers = {'User-Agent': USER_AGENT}
    response = requests.get(url, headers=headers)
    # print(response.content.decode())
    soup = BeautifulSoup(response.content, 'html.parser')
    ReadInfo = soup.find(class_='x-wiki-info')
    num = int(ReadInfo.span.string.split(':')[1])
    return num
    # print(num)


async def read_num_asyncio(url,index,sem):
    # 要模擬瀏覽器登陸
    headers = {'User-Agent': USER_AGENT}
    with (await sem):
        async with aiohttp.ClientSession() as client:
            async with client.get(url, headers=headers) as resp:
                assert resp.status == 200
                txt = await resp.text()

        # async with aiohttp.get(url, headers=headers) as resp:
        #     assert resp.status == 200
        #     txt = await resp.text()
        #     # print(txt)

        soup = BeautifulSoup(txt,'html.parser')
        read_info = soup.find(class_='x-wiki-info')
        num = int(read_info.span.string.split(':')[1])
        # print(num)
        global NUM_LEFT,READING_INFO
        READING_INFO[index] = num
        NUM_LEFT += 1
        print(NUM_LEFT)
        # return num


# 異步方法讀取100+個教程網(wǎng)頁然后提取出閱讀量
def asyncio_get_reading_num(urls):
    # 設(shè)置線程的信號量撞鹉,最多5個協(xié)程在工作,根據(jù)網(wǎng)站的流量或者實際測試確定
    # 如果沒有進(jìn)行限制,那么中途可能被封IP
    sem = asyncio.Semaphore(5)
    loop = asyncio.get_event_loop()
    # tasks = [read_num_asyncio(url,index,sem) for index,url in enumerate(urls) if index < 20]
    tasks = [read_num_asyncio(url, index, sem) for index, url in enumerate(urls)]
    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()


@timing
def main():
    urls = get_all_urls()
    print(len(urls))


    global READING_INFO
    READING_INFO = [0] * len(urls)

    asyncio_get_reading_num(urls)


    # all_readInfo = []
    # urls_num = len(urls)
    # for i,url in enumerate(urls):
    #     if i <= 40:
    #         num = read_num(url)
    #         if num is not None:
    #             all_readInfo.append(num)
    #         print(i)
    #     else:
    #         break

    plt.plot(READING_INFO)
    plt.show()

if __name__ == '__main__':
    main()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸟雏,一起剝皮案震驚了整個濱河市享郊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌孝鹊,老刑警劉巖炊琉,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異又活,居然都是意外死亡苔咪,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門柳骄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悼泌,“玉大人,你說我怎么就攤上這事夹界」堇铮” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵可柿,是天一觀的道長鸠踪。 經(jīng)常有香客問我,道長复斥,這世上最難降的妖魔是什么营密? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮目锭,結(jié)果婚禮上评汰,老公的妹妹穿的比我還像新娘。我一直安慰自己痢虹,他們只是感情好被去,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著奖唯,像睡著了一般惨缆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上丰捷,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天坯墨,我揣著相機(jī)與錄音,去河邊找鬼病往。 笑死捣染,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的停巷。 我是一名探鬼主播耍攘,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼累贤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了少漆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤硼被,失蹤者是張志新(化名)和其女友劉穎示损,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嚷硫,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡检访,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了仔掸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脆贵。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖起暮,靈堂內(nèi)的尸體忽然破棺而出卖氨,到底是詐尸還是另有隱情,我是刑警寧澤负懦,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布筒捺,位于F島的核電站,受9級特大地震影響纸厉,放射性物質(zhì)發(fā)生泄漏系吭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一颗品、第九天 我趴在偏房一處隱蔽的房頂上張望肯尺。 院中可真熱鬧,春花似錦躯枢、人聲如沸则吟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逾滥。三九已至,卻和暖如春败匹,著一層夾襖步出監(jiān)牢的瞬間寨昙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工掀亩, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留舔哪,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓槽棍,卻偏偏與公主長得像捉蚤,于是被迫代替她去往敵國和親抬驴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,749評論 25 707
  • 學(xué)習(xí)傳習(xí)錄大有好處缆巧,可以讓我知道我是誰布持?我能做什么?或者又說陕悬,我的成就為什么不像我想要的那么大题暖。為什么呢?是我的仁...
    姜天合閱讀 496評論 0 3
  • 以下是閱讀《精進(jìn)》的第三章行動中的筆記捉超,以下是具體的反思方法論 (一)信息 做這件事時胧卤,我利用了哪些信息? 哪些信...
    欣欣向榮的小天地閱讀 231評論 0 0