1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        爬蟲 | urllib入門+糗事百科實(shí)戰(zhàn)

        共 5546字,需瀏覽 12分鐘

         ·

        2021-03-29 12:05

        所謂爬蟲(crawler),是指一只小蟲子,在網(wǎng)絡(luò)中爬行,見(jiàn)到有用的東西就會(huì)把它拿下來(lái),是我們獲取信息的一個(gè)重要途徑。平常使用的瀏覽器,它的背后就是一個(gè)巨大的爬蟲框架,輸入我們想要查找的信息,幫我們爬取下來(lái)。今天就從較為簡(jiǎn)單的urllib爬蟲開(kāi)始介紹。



        Urllib庫(kù)是python內(nèi)置的一個(gè)爬蟲庫(kù),現(xiàn)在常用的有requests,它是對(duì)urllib進(jìn)行了進(jìn)一步的封裝,今天先從urllib入手,后續(xù)再聊requests等的使用。根據(jù)我的風(fēng)格來(lái)說(shuō),當(dāng)然是有實(shí)際操作大家更容易理解,所以說(shuō),本文仍然是從代碼入手,帶你實(shí)現(xiàn)第一個(gè)爬蟲小栗子。


        官方的介紹如下:

        urllib is a package that collects several modules for working with URLs:

        • urllib.request for opening and reading URLs

        • urllib.error containing the exceptions raised by urllib.request

        • urllib.parse for parsing URLs

        • urllib.robotparser for parsing robots.txt files


        上面的四塊其實(shí)很容易理解,分別是請(qǐng)求內(nèi)容、異常處理、URL解析以及robot協(xié)議解析。不過(guò)今天不介紹那么多,有疑問(wèn)的話可以自行查詢相應(yīng)的內(nèi)容,今天的任務(wù)是入門,以及實(shí)現(xiàn)一個(gè)小爬蟲。



        發(fā)送請(qǐng)求


        # 導(dǎo)入請(qǐng)求庫(kù)
        import urllib.request

        # 向指定的url地址發(fā)送請(qǐng)求并返回服務(wù)器響應(yīng)的數(shù)據(jù)(文件的對(duì)象)
        response = urllib.request.urlopen("http://www.baidu.com")

        # 讀取文件的全部?jī)?nèi)容,會(huì)把讀到的東西賦值給一個(gè)字符串變量
        data = response.read()


        簡(jiǎn)單三行代碼就得到了我們所要的內(nèi)容,可以查看一下data中的信息,其實(shí)這就形成了我們?cè)跒g覽器中看到的內(nèi)容,可以通過(guò)瀏覽器頁(yè)面F12查看。



        response是我們請(qǐng)求百度首頁(yè)返回的響應(yīng),可以通過(guò)這個(gè)響應(yīng)查看這次請(qǐng)求的一些信息。例如:


        response.info() 返回當(dāng)前環(huán)境的一些信息(日期、cookies等)
        response.getcode() 返回狀態(tài)碼(200代表正常訪問(wèn)等)
        response.geturl() 返回正在爬取的地址



        寫入文件


        其實(shí)獲取到信息,存儲(chǔ)到文件就很方便了,可以參考【python文件操作】,不過(guò)在urllib庫(kù)中還有一個(gè)直接將爬取到的內(nèi)容存到文件的方法。


        import urllib.request

        urllib.request.urlretrieve("http://www.baidu.com",
                                   filename=r"F:/demo/file.html")
        # urlretrieve在執(zhí)行過(guò)程中,會(huì)產(chǎn)生一些緩存
        # 清除緩存
        urllib.request.urlcleanup()



        模擬瀏覽器


        現(xiàn)在爬蟲發(fā)展的非常快,而爬蟲給網(wǎng)站帶來(lái)的壓力也不小,因此,越來(lái)越多的網(wǎng)站在研究它的反爬機(jī)制。也就是發(fā)現(xiàn)你是一個(gè)爬蟲而非人工的訪問(wèn),并且對(duì)自己的網(wǎng)站造成壓力等,那么就會(huì)采取措施,比如禁止你的訪問(wèn)、封掉你的IP等等。說(shuō)這些什么意思呢?既然人家不讓爬,那么我們可以偽裝一下,假裝自己是正常訪問(wèn)。當(dāng)然這也是不容易的,不過(guò)有一些最基本的操作,還是可以輕松理解的。


        對(duì)于使用python來(lái)進(jìn)行爬蟲,其實(shí)是可以直接看到你是一個(gè)python爬蟲的,直接告訴人家是個(gè)爬蟲,那想禁你還不輕松。因此,首先針對(duì)這個(gè)問(wèn)題,可以采用模擬瀏覽器的方式來(lái)解決。在發(fā)起請(qǐng)求后,請(qǐng)求頭中包含一個(gè)user-agent字段,修改這個(gè)內(nèi)容就可以了。


        import urllib.request

        url = "http://www.baidu.com"

        # 模擬請(qǐng)求頭
        headers = {
          "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3493.3 Safari/537.36"
        }

        # 設(shè)置一個(gè)請(qǐng)求體
        req = urllib.request.Request(url, headers=headers)

        # 發(fā)起請(qǐng)求
        response = urllib.request.urlopen(req)


        關(guān)于User-Agent在網(wǎng)上可以找到很多,或者打開(kāi)自己的瀏覽器,F(xiàn)12->network,隨便點(diǎn)一個(gè)網(wǎng)頁(yè)找request headers即可。



        超時(shí)設(shè)置


        在爬蟲的過(guò)程中難免會(huì)遇到請(qǐng)求不到內(nèi)容的情況,當(dāng)它無(wú)法繼續(xù)爬取的時(shí)候我們也不能一直和它耗著不是,而且如果是爬蟲期間的某一個(gè)地址訪問(wèn)不到,也不能讓它影響后面的工作,因此,設(shè)置超時(shí)是有必要的。操作也很方便,只需要在打開(kāi)頁(yè)面的時(shí)候添加個(gè)timeout參數(shù)即可。


        import urllib.request

        # 如果網(wǎng)頁(yè)長(zhǎng)時(shí)間未響應(yīng),系統(tǒng)判斷超時(shí),無(wú)法爬取
        try:
            response = urllib.request.urlopen("http://www.baidu.com", timeout=0.1)
        except:
            print("time out")



        HTTP請(qǐng)求


        主要的HTTP請(qǐng)求有以下幾種,最常用的就是get和post。

        GET: 通過(guò)url網(wǎng)址傳遞信息,可以直接在url網(wǎng)址上添加要傳遞的信息(不安全) POST: 可以向服務(wù)器提交數(shù)據(jù),是一種比較流行,安全的數(shù)據(jù)傳遞方式 

        PUT: 請(qǐng)求服務(wù)器存儲(chǔ)一個(gè)資源,通常要指定存儲(chǔ)的位置 

        DELETE: 請(qǐng)求服務(wù)器刪除一個(gè)資源 

        HEAD: 請(qǐng)求獲取對(duì)應(yīng)的http報(bào)頭信息 

        OPTIONS: 可以獲取當(dāng)前url所支持的請(qǐng)求類型


        • get請(qǐng)求:

        特點(diǎn):把數(shù)據(jù)拼接到請(qǐng)求路徑后面?zhèn)鬟f給服務(wù)器

        優(yōu)點(diǎn):速度快

        缺點(diǎn):承載的數(shù)據(jù)量小,不安全


        • post請(qǐng)求:

        特點(diǎn):把參數(shù)進(jìn)行打包,單獨(dú)傳輸

        優(yōu)點(diǎn):數(shù)量大,安全(當(dāng)對(duì)服務(wù)器數(shù)據(jù)進(jìn)行修改時(shí)建議使用post)

        缺點(diǎn):速度慢


        下面舉個(gè)栗子,這就需要用到開(kāi)始提到的第二個(gè)方法parse。


        import urllib.request
        import urllib.parse # 對(duì)請(qǐng)求打包的庫(kù)

        url = "http://httpbin.org/post"
        # 將要發(fā)送的數(shù)據(jù)合成一個(gè)字典
        data = {
            "name": "xiaotian"
        }
        # 對(duì)要發(fā)送的數(shù)據(jù)進(jìn)行打包
        postdata = urllib.parse.urlencode(data).encode("utf-8")

        # 請(qǐng)求體
        req = urllib.request.Request(url, data=postdata)

        # 請(qǐng)求
        response = urllib.request.urlopen(req)
        print(response.read())




        實(shí)戰(zhàn)演練


        開(kāi)始寫程序之前,一定要先分析網(wǎng)頁(yè)。選取糗事百科的段子來(lái)爬一下,網(wǎng)址在這(https://www.qiushibaike.com/text/)。



        既然是爬取上面的段子,首先要找到段子對(duì)應(yīng)網(wǎng)頁(yè)中的什么位置,打開(kāi)F12(前面一直說(shuō)F12,其實(shí)就是打開(kāi)網(wǎng)頁(yè)的源碼),左上角有個(gè)箭頭,可以點(diǎn)擊它,用來(lái)快速找到網(wǎng)頁(yè)顯示部分與源碼的對(duì)應(yīng)。



        可以看到上方,鼠標(biāo)所在位置的顏色可以對(duì)應(yīng)找到源碼。找到一個(gè)段子的源碼,那緊接著就是找我們想要的內(nèi)容,例如發(fā)布段子的用戶名,以及段子的內(nèi)容等。當(dāng)然,今天的內(nèi)容都是初級(jí)的爬蟲,想要的信息都在這樣一個(gè)靜態(tài)網(wǎng)頁(yè)中,找到如下的內(nèi)容,然后利用正則表達(dá)式來(lái)提取其中的信息?!?a target="_blank" data-itemshowtype="0" tab="innerlink" data-linktype="2">正則表達(dá)式】




        import urllib.request
        import re

        def jokeCrawler(url):
            headers = {
                "User-Agent": "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10"
            }
            req = urllib.request.Request(url, headers=headers)
            response = urllib.request.urlopen(req)

            html = response.read().decode("utf-8")

            pat = r'<div class="author clearfix">(.*?)<span class="stats-vote"><i class="number">'
            re_joke = re.compile(pat, re.S) # re.S 使可以匹配換行
            divsList = re_joke.findall(html)

            dic = {}
            for div in divsList:
                # 用戶名
                re_u = re.compile(r"<h2>(.*?)</h2>", re.S)
                username = re_u.findall(div)
                username = username[0].rstrip()
                # 段子
                re_d = re.compile(r'<div class="content">\n<span>(.*?)</span>', re.S)
                duanzi = re_d.findall(div)
                duanzi = duanzi[0].strip()
                dic[username] = duanzi
            return dic

        url = "https://www.qiushibaike.com/text/page/1/"
        info = jokeCrawler(url)
        for k, v in info.items():
            print(k + ':\n' + v)



        上面我所做的內(nèi)容比較粗糙,可以自行再處理一下正則表達(dá)式。這只是爬取了一頁(yè)的內(nèi)容,嘗試把URL中的page換個(gè)數(shù)字就會(huì)發(fā)現(xiàn),可以做到翻頁(yè),假如使用循環(huán),可以爬蟲更多的內(nèi)容,后面就可以自行探索了。


        推薦閱讀
        誤執(zhí)行了rm -fr /*之后,除了跑路還能怎么辦?!
        程序員必備58個(gè)網(wǎng)站匯總
        大幅提高生產(chǎn)力:你需要了解的十大Jupyter Lab插件

        瀏覽 42
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            骚屄网| 天天操夜夜拍 | 刑讯室a级妇刑酷刑视频 | 网友激情自拍 | 人人摸人人舔人人操 | jizz丝袜壮感的18老师不卡 | 鸡巴天堂 | 日韩大香蕉视频 | 边添边摸边做边爱免费 | 偷拍大学生情侣无套进入 |