1. 程式人生 > >爬取貼吧頁面

爬取貼吧頁面

turn tex max request 完成 發送 span fragment 代碼

Get方式

GET請求一般用於我們向服務器獲取數據,比如說,我們用百度搜索傳智播客:https://www.baidu.com/s?wd=傳智播客

瀏覽器的url會跳轉成如圖所示:

技術分享圖片

https://www.baidu.com/s?wd=%E4%BC%A0%E6%99%BA%E6%92%AD%E5%AE%A2

在其中我們可以看到在請求部分裏,http://www.baidu.com/s? 之後出現一個長長的字符串,其中就包含我們要查詢的關鍵詞傳智播客,於是我們可以嘗試用默認的Get方式來發送請求。

from urllib import request, parse    # parse負責url編碼處理

url = "http://www.baidu.com/s"
word = {"wd":"傳智播客"}
word = parse.urlencode(word)  #轉換成url編碼格式(字符串)
newurl = url + "?" + word    # url首個分隔符就是 ?

headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"}

req = request.Request(newurl, headers=headers)

response = request.urlopen(req)

print(response.read())

批量爬取貼吧頁面數據

首先我們創建一個python文件, tiebaSpider.py,我們要完成的是,輸入一個百度貼吧的地址,比如:

百度貼吧LOL吧第一頁:http://tieba.baidu.com/f?kw=lol&ie=utf-8&pn=0

第二頁: http://tieba.baidu.com/f?kw=lol&ie=utf-8&pn=50

第三頁: http://tieba.baidu.com/f?kw=lol&ie=utf-8&pn=100

發現規律了吧,貼吧中每個頁面不同之處,就是url最後的pn的值,其余的都是一樣的,我們可以抓住這個規律。

簡單寫一個小爬蟲程序,來爬取百度LOL吧的所有網頁。
  • 先寫一個main,提示用戶輸入要爬取的貼吧名,並用 urllib.parse.urlencode()進行轉碼,然後組合url,假設是lol吧,那麽組合後的url就是:http://tieba.baidu.com/f?kw=lol
# 模擬 main 函數
if __name__ == "__main__":

    kw = input("請輸入需要爬取的貼吧:")
    # 輸入起始頁和終止頁,str轉成int類型
    beginPage = int(input("請輸入起始頁:"))
    endPage = int(input("請輸入終止頁:"))

    url = "http://tieba.baidu.com/f?"
    key = urllib.parse.urlencode({"kw" : kw})

    # 組合後的url示例:http://tieba.baidu.com/f?kw=lol
    url = url + key
    tiebaSpider(url, beginPage, endPage)
  • 接下來,我們寫一個百度貼吧爬蟲接口,我們需要傳遞3個參數給這個接口, 一個是main裏組合的url地址,以及起始頁碼和終止頁碼,表示要爬取頁碼的範圍。
def tiebaSpider(url, beginPage, endPage):
    """
        作用:負責處理url,分配每個url去發送請求
        url:需要處理的第一個url
        beginPage: 爬蟲執行的起始頁面
        endPage: 爬蟲執行的截止頁面
    """


    for page in range(beginPage, endPage + 1):
        pn = (page - 1) * 50

        filename = "第" + str(page) + "頁.html"
        # 組合為完整的 url,並且pn值每次增加50
        fullurl = url + "&pn=" + str(pn)
        #print(fullurl)

        # 調用loadPage()發送請求獲取HTML頁面
        html = loadPage(fullurl, filename)
        # 將獲取到的HTML頁面寫入本地磁盤文件
        writeFile(html, filename)
  • 我們已經之前寫出一個爬取一個網頁的代碼。現在,我們可以將它封裝成一個小函數loadPage,供我們使用。
def loadPage(url, filename):
    ‘‘‘
        作用:根據url發送請求,獲取服務器響應文件
        url:需要爬取的url地址
        filename: 文件名
    ‘‘‘
    print("正在下載" + filename)

    headers = {"User-Agent": "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}

    req = urllibrequest.Request(url, headers = headers)
    response = request.urlopen(req)
    return response.read()
  • 最後如果我們希望將爬取到了每頁的信息存儲在本地磁盤上,我們可以簡單寫一個存儲文件的接口。
def writeFile(html, filename):
    """
        作用:保存服務器響應文件到本地磁盤文件裏
        html: 服務器響應文件
        filename: 本地磁盤文件名
    """
    print "正在存儲" + filename
    with open(filename, ‘w‘, encoding=‘utf-8‘) as f:
        f.write(html)
    print "-" * 20

完整代碼:

技術分享圖片
from urllib import request, parse
import sys


def loadPage(url, filename):
    """
    作用: 根據url發送請求, 獲取服務器相應文件
    url: 需要爬取的url地址
    """
    print("正在下載" + filename)
    headers = {
        "User-Agent": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"
    }
    req = request.Request(url, headers=headers)
    # 獲得系統的編碼
    type = sys.getfilesystemencoding()
    # 設置爬出內容的編碼
    print(type)
    # ************************************************
    html = request.urlopen(req).read().decode(type)
    # ************************************************
    print(html)
    return html


def writePage(html, filename):
    """
    作用: 將html內容寫入到本地
    html: 服務器相應文件內容
    """
    print("正在保存" + filename)
    # ***********************************************
    with open(filename, "w", encoding="utf-8") as f:
        # ***********************************************
        f.write(html)
    print("*" * 30)


def tiebaSpider(url, bingenPage, endPage):
    """
    作用: 爬蟲爬蟲調度器, 負責組合處理每一個頁面的url
    url: 貼吧url的前部分,
    beginPage: 起始頁
    endPage: 終止頁
    """
    for page in range(beginPage, endPage + 1):
        pn = (page - 1) * 50
        filename = "" + str(page) + "頁.html"
        fullurl = url + "&pn=" + str(pn)
        print(fullurl)
        html = loadPage(fullurl, filename)
        writePage(html, filename)


if __name__ == "__main__":
    kw = input("請輸入需要爬取的貼吧名:")
    beginPage = int(input("請輸入起始頁編號"))
    endPage = int(input("請輸入結束頁編號:"))
    url = "http://tieba.baidu.com/f?"
    key = parse.urlencode({"kw": kw})
    fullurl = url + key
    tiebaSpider(fullurl, beginPage, endPage)
View Code

其實很多網站都是這樣的,同類網站下的html頁面編號,分別對應網址後的網頁序號,只要發現規律就可以批量爬取頁面了。

爬取貼吧頁面