不知道網(wǎng)頁(yè)鏈接如何爬取數(shù)據(jù)(一)

前言:有些時(shí)候,我們?cè)诓橐恍┍容^老的數(shù)據(jù)窥摄,由于網(wǎng)站升級(jí)镶奉,或者改版之類的,我們無(wú)法得到我們想要數(shù)據(jù)的網(wǎng)址崭放,也就無(wú)法爬取數(shù)據(jù)哨苛,下面,我將帶大家一起來(lái)分析一下自己的案例币砂。

  1. 明確需求
    背景:在網(wǎng)上搜自己的名字建峭,居然找到一份文檔,大概是這樣的樣子2015年普通高校招生錄取名單公示(五) (sxkszx.cn) 然后就順騰摸瓜决摧,想找到全部的數(shù)據(jù)——2015年全部的數(shù)據(jù)

  2. 查找數(shù)據(jù)
    剛開始亿蒸,由于找到了網(wǎng)站,2015年普通高校招生錄取名單公示(五) (sxkszx.cn)掌桩,網(wǎng)址是http://www.sxkszx.cn/边锁,我想在網(wǎng)站搜索,但是發(fā)現(xiàn)網(wǎng)站沒(méi)有搜索功能波岛,而且茅坛,更要命的是,這個(gè)每一頁(yè)则拷,沒(méi)有上一頁(yè)贡蓖,下一頁(yè)的鏈接,這樣我們就找不到相關(guān)聯(lián)的數(shù)據(jù)煌茬。
    而且斥铺,我們發(fā)現(xiàn),網(wǎng)址的拼接也是很奇怪宣旱,http://www.sxkszx.cn/news/2015722/n82552675.html仅父,news代表新聞叛薯,2015722代表發(fā)布日期,后面的n82552675就很奇怪笙纤,如果改成n82552676則會(huì)404耗溜,也就是無(wú)法單純的修改最后一位來(lái)完成地址的模擬

  3. 使用搜索引擎增強(qiáng)搜索力度
    現(xiàn)在進(jìn)入了困境,我們無(wú)法在該網(wǎng)站查找省容。不過(guò)我們可是使用
    2015年普通高校招生錄取名單 site:sxkszx.cn
    來(lái)進(jìn)行網(wǎng)站的查找抖拴,這樣是使用搜索引擎來(lái)進(jìn)行該網(wǎng)站的搜索,在百度地址欄輸入搜索即可腥椒。
    然后我們會(huì)找到

    image.png

    很多數(shù)據(jù)被找到了阿宅,然后我們分析一下,發(fā)現(xiàn)其中缺少了一些公示笼蛛,這意味這數(shù)據(jù)不太完整洒放。

  4. 網(wǎng)站地址分析 + 試探
    現(xiàn)在問(wèn)題又回到了原點(diǎn),我們不知道網(wǎng)頁(yè)的網(wǎng)址滨砍,那么就無(wú)法爬取數(shù)據(jù)往湿。但是,現(xiàn)在要比最開始好很多惋戏,因?yàn)楝F(xiàn)在除了錄取名單五以外领追,還多了很多,以供我們分析响逢。

    • 整理一下绒窑,來(lái)分析一下數(shù)據(jù)的異同
image.png

為了能夠看出其中的異同,我把數(shù)據(jù)一行一行列了出來(lái)舔亭,然后行號(hào)就是公示名單的數(shù)字標(biāo)號(hào)(空缺部分表示目前未知的網(wǎng)站鏈接)

現(xiàn)在分析一下網(wǎng)址些膨,我們發(fā)現(xiàn),最后四位數(shù)字好像是遞增的


image.png

對(duì)钦铺,這有點(diǎn)像是傀蓉,新聞在數(shù)據(jù)庫(kù)中存儲(chǔ)的編號(hào)id,意味著這是第2669篇新聞职抡,那么葬燎,第2670篇新聞的網(wǎng)址應(yīng)該是怎樣的呢?
推測(cè)如下

http://www.sxkszx.cn/news/日期/n四位不知名數(shù)字2670
且日期應(yīng)當(dāng)是在2015.7.22當(dāng)天缚甩,或者之后

講道理谱净,我們這里應(yīng)該要分析 四位不知名數(shù)字 的含義,或者討論它是如何生成的擅威,但是筆者想了很多壕探,都沒(méi)能猜到,之前猜測(cè)或者與時(shí)間/文章名字/等等郊丛,但是都不太對(duì)李请,總之沒(méi)能猜到瞧筛。

  • 由于我們沒(méi)猜到,所以我們有一個(gè)最樸素的想法导盅,我們遍歷0000-9999不就可以了嗎较幌?找到那個(gè)可以正確返回的鏈接
    對(duì),這個(gè)想法很正確白翻。
下面的這一段代碼乍炉,返回了一個(gè)列表,列表中包含了從0000-9999的所有可能的網(wǎng)址鏈接
def gene_urls():
    base_url = "http://www.sxkszx.cn/news/"
    date = "2015820"
    newsId = "2745"
    urls = []
    for i in range(1, 10000):
        s = str(i).zfill(4)
        url = base_url + date + "/n" + s + newsId + ".html"
        urls.append(url)
    return urls

寫到這里滤馍,大家可能覺(jué)得岛琼,這不很簡(jiǎn)單嗎?直接

for url in urls:
  response = requests.get(url)
  if response.status.code == 200:
      print url
      break

但是巢株,這是很樸素的單線程槐瑞,我們做一個(gè)計(jì)算
我們大概空缺的是

日期     新聞id
722      2675
723      2676
...         
83

         ...
         2696

我們發(fā)現(xiàn),一次嘗試阁苞,都要花費(fèi)很長(zhǎng)的時(shí)間随珠,如果我們想要全部試探,需要很長(zhǎng)的時(shí)間猬错,且,requests要不斷斷開茸歧,建立連接倦炒,花銷很大。

下面软瞎,我們嘗試多線程逢唤。
下面是一份很長(zhǎng)的代碼,大家不用關(guān)心具體怎么實(shí)現(xiàn)的涤浇,只要知道
single_thread 代表單線程
multi_thread 代表多線程
即可

# 不斷嘗試url鳖藕,當(dāng)返回不是404,則加入my_urls.txt中

import requests
import threading
import requests.adapters
import time

base_url = "http://www.sxkszx.cn/news/"
date = "2015722"
newsId = "2678"

# f = open("my_urls.txt", 'w+')

flag = 0
# count = 0


def gene_urls():
    urls = []
    for i in range(1, 10000):
        s = str(i).zfill(4)
        url = base_url + date + "/n" + s + newsId + ".html"
        urls.append(url)
    return urls


def test_url(url):
    # response = requests.get(url=url, timeout=30)
    # if response.status_code == 200:
    #     print(url)

    # try:
    #     with requests.get(url, timeout=5) as r:
    #         if r.status_code == 200:
    #             flag = 1
    #             print(url)
    # except:
    #     print("處理異常中...")
    #     time.sleep(5)
    global flag
    if flag == 0:
        response = None
        global count
        try:
            # 設(shè)置重連次數(shù)
            requests.adapters.DEFAULT_RETRIES = 5
            s = requests.session()
            # 設(shè)置連接活躍狀態(tài)為False
            s.keep_alive = False
            response = requests.get(url, stream=False, timeout=10)
            if response.status_code == 200:
                flag = 1
                print(url)
            # 關(guān)閉請(qǐng)求  釋放內(nèi)存
            response.close()
            del (response)
        except Exception as indentfier:
            time.sleep(5)


def single_thread(need_test_urls):
    for url in need_test_urls:
        global flag
        if flag == 0:
            test_url(url)
        else:
            break


def multi_thread(need_test_urls):
    threads = []
    for url in need_test_urls:
        threads.append(
            threading.Thread(target=test_url, args=(url,))
        )

    for thread in threads:
        thread.start()

    for thread in threads:
        thread.join()

    print("ok")


if __name__ == "__main__":
    u = gene_urls()
    multi_thread(u)
    # single_thread(u)

但是問(wèn)題到這里還沒(méi)有結(jié)束只锭,盡管編寫上面的代碼著恩,已經(jīng)踩了很多的坑,包括 如requests未斷開蜻展;未手動(dòng)斷開(采用with 語(yǔ)句喉誊,自動(dòng)斷開會(huì)導(dǎo)致他會(huì)慢慢斷開,還是會(huì)報(bào)錯(cuò)纵顾,max tries伍茄,服務(wù)器中止...);
但是新的問(wèn)題又來(lái)了施逾,我發(fā)現(xiàn)這個(gè)代碼在有的 日期 + 新聞id上可以運(yùn)行出結(jié)果來(lái)敷矫,有的則不會(huì)例获,具體原因我也不太清楚,評(píng)論區(qū)的小伙伴有知道的曹仗,可以告訴一下我榨汤,謝謝~

  1. scrapy框架的使用
    最后的最后,我實(shí)在受不了了整葡,我大概明白件余,應(yīng)該是并發(fā)的時(shí)候,導(dǎo)致requests的連接無(wú)法斷開遭居,或者斷開需要時(shí)間啼器,但是還沒(méi)有斷開的這個(gè)期間,新的請(qǐng)求已經(jīng)發(fā)送了俱萍,這樣就會(huì)有一部分請(qǐng)求是沒(méi)有效果的端壳,也就是一部分鏈接被卡掉了。

而這個(gè)枪蘑,是目前的我所解決不了的损谦。

于是我想著試一下scrapy,因?yàn)槲抑奥?tīng)過(guò)scrapy岳颇,但是沒(méi)有用過(guò)照捡,想著用它來(lái)解決并發(fā)問(wèn)題,會(huì)不會(huì)好點(diǎn)话侧。

先說(shuō)實(shí)驗(yàn)結(jié)果栗精,最終成功解決了并發(fā)問(wèn)題,對(duì)于每一個(gè) 日期 + 新聞id 所產(chǎn)生的鏈接列表瞻鹏,大概在1mins內(nèi)可以得到結(jié)果悲立,已經(jīng)算是很快了。

再說(shuō)下去新博,就要講scrapy框架了薪夕,但是現(xiàn)在我好餓,我先去吃個(gè)飯飯赫悄,寶寶餓了

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末原献,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子埂淮,更是在濱河造成了極大的恐慌嚼贡,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件同诫,死亡現(xiàn)場(chǎng)離奇詭異粤策,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)误窖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門叮盘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)秩贰,“玉大人,你說(shuō)我怎么就攤上這事柔吼《痉眩” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵愈魏,是天一觀的道長(zhǎng)觅玻。 經(jīng)常有香客問(wèn)我,道長(zhǎng)培漏,這世上最難降的妖魔是什么溪厘? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮牌柄,結(jié)果婚禮上畸悬,老公的妹妹穿的比我還像新娘。我一直安慰自己珊佣,他們只是感情好蹋宦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著咒锻,像睡著了一般冷冗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上惑艇,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天蒿辙,我揣著相機(jī)與錄音,去河邊找鬼敦捧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛碰镜,可吹牛的內(nèi)容都是我干的兢卵。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼绪颖,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼秽荤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起柠横,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤窃款,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后牍氛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體晨继,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年搬俊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了紊扬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜒茄。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖餐屎,靈堂內(nèi)的尸體忽然破棺而出檀葛,到底是詐尸還是另有隱情,我是刑警寧澤腹缩,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布屿聋,位于F島的核電站,受9級(jí)特大地震影響藏鹊,放射性物質(zhì)發(fā)生泄漏润讥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一伙判、第九天 我趴在偏房一處隱蔽的房頂上張望象对。 院中可真熱鬧,春花似錦宴抚、人聲如沸勒魔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)冠绢。三九已至,卻和暖如春常潮,著一層夾襖步出監(jiān)牢的瞬間弟胀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工喊式, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留孵户,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓岔留,卻偏偏與公主長(zhǎng)得像夏哭,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子献联,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

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