久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

前后端分離有什么了不起,手把手教你用Python爬下來,!

 鷹擊彩霞 2021-01-15

大家好,我是早起。

本文一個詳細(xì)的爬蟲進(jìn)階教程,,里面包含了很詳細(xì)的思考和試錯過程,如果你對學(xué)爬蟲是認(rèn)真的,,建議認(rèn)真看,。

我們要抓取下面這個網(wǎng)站上的所有圖書列表:

https://www./books

1) 探索研究

創(chuàng)建一個新的python文件,寫入如下代碼:

import requests
url = 'https://www./books'
res = requests.get(url)
print(res.text)

運(yùn)行發(fā)現(xiàn)打印結(jié)果如下:

這里面根本沒有圖書的信息,。但使用瀏覽器檢查器可以看到圖書的信息:

我們碰到了一個基于前后端分離的網(wǎng)站,,或者說一個用JavaScript獲取數(shù)據(jù)的網(wǎng)站。這種網(wǎng)站的數(shù)據(jù)流程是這樣的:

  • 初次請求只返回了網(wǎng)頁的基本框架,,并沒有數(shù)據(jù),。就是前面截圖看到那樣。
  • 但網(wǎng)頁的基本框架中包含JavaScript的代碼,,這段代碼會再發(fā)起一次或者多次請求獲取數(shù)據(jù),。我們稱為后續(xù)請求

為了抓取這樣的網(wǎng)站,,有兩個辦法:

  1. 分析出后續(xù)請求的地址和參數(shù),,寫代碼發(fā)起同樣的后續(xù)請求。
  2. 使用模擬瀏覽器技術(shù),,比如selenium,。這種技術(shù)可以自動發(fā)起后續(xù)請求獲取數(shù)據(jù)。

2) 分析后續(xù)請求

打開谷歌瀏覽器的檢查器,,按圖中的指示操作:

  1. 點(diǎn)擊Network,,這里可以查看瀏覽器發(fā)送的所有網(wǎng)絡(luò)請求。
  2. XHR,,查看瀏覽器用JavaScript發(fā)送的請求,。
  3. 下面可以看到很多請求。我們要一個個看過去找到包含商品列表的請求,。

再來理解一下瀏覽器打開一個網(wǎng)頁的過程,,一般并不是一個請求返回了所有的內(nèi)容,而是包含多個步驟:

  1. 第一個請求獲得HTML文件,,里面可能包含文字,,數(shù)據(jù),圖片的地址,樣式表地址等,。HTML文件中并沒有直接包含圖片,。
  2. 瀏覽器根據(jù)HTML中的鏈接,再次發(fā)送請求,,讀取圖片,,樣式表,基于JavaScript的數(shù)據(jù)等,。

所以我們看到有這么不同類型的請求:XHR, JS,,CSS,Img,,F(xiàn)ont, Doc等,。

我們爬取的網(wǎng)站發(fā)送了很多個XHR請求,分別用來請求圖書列表,,網(wǎng)頁的菜單,,廣告信息,頁腳信息等,。我們要從這些請求中找出圖書的請求,。

具體操作步驟如圖:

  1. 在左邊選中請求
  2. 在右邊選擇Response
  3. 下面可以看到這個請求返回的數(shù)據(jù),從數(shù)據(jù)可以判斷是否包含圖書信息,。

Javascript請求返回的格式通常是JSON格式,,這是一種JavaScript的數(shù)據(jù)格式,里面包含用冒號隔開的一對對數(shù)據(jù),,比較容易看懂,。JSON很像Python中的字典。

在眾多的請求中,,可以根據(jù)請求的名字大致判斷,,提高效率。比如上圖中g(shù)etUBookList看起來就像是獲取圖書列表,。點(diǎn)開查看,,返回的果然是圖書列表。

請記住這個鏈接的地址和格式,,后面要用到:

https://www./pubcloud/content/front/portal/getUbookList?page=1&row=20&=&startPrice=&endPrice=&tagId= 分析一下,,可以看到:

  1. 網(wǎng)址是:https://www./pubcloud/content/front/portal/getUbookList
  2. page=1表示第1頁,我們可以依次傳入2,,3,,4等等。
  3. row=20表示每一頁有20本書
  4. startPrice和endPrice表示價格條件,,他們的值都是空,,表示不設(shè)定價格限制。

3) 使用postman測試猜想

為了驗證這個設(shè)想打開谷歌瀏覽器,,在地址欄中輸入以下網(wǎng)址:

https://www./pubcloud/content/front/portal/getUbookList?page=1&row=20&=&startPrice=&endPrice=&tagId=

可是得到了如下的返回結(jié)果:

{
    'code''-7',
    'data'null,
    'msg''系統(tǒng)臨時開小差,,請稍后再試~',
    'success'false
}

這并不是系統(tǒng)出了問題,而是系統(tǒng)檢測到我們是非正常的請求,,拒絕給我們返回數(shù)據(jù),。

這說明除了發(fā)送這個URL,還需要給服務(wù)器傳送額外的信息,,這些信息叫做Header,,翻譯成中文是請求頭的意思。

在下圖中可以看到正常的請求中包含了多個請求頭:

  1. 選中要查看的請求
  2. 在右邊選Headers
  3. 往下翻,,可以看到Request Headers,,下面就是一項項數(shù)據(jù):
    • Accept: application/json, text/plain, /
    • Accept-Encoding:gzip, deflate, br
    • ....

為了讓服務(wù)器正常處理請求,我們要模擬正常的請求,,也添加相應(yīng)的header,。如果給的Header也都一樣,服務(wù)器根本不可能識別出我們是爬蟲,。后面我們會學(xué)習(xí)如何在發(fā)送請求時添加header,。

但通常服務(wù)器并不會檢查所有的Header,可能只要添加一兩個關(guān)鍵Header就可以騙服務(wù)器給我們數(shù)據(jù)了,。但我們要一個個測試那些Header是必須的,。

在瀏覽器中無法添加Header,為了發(fā)送帶Header的HTTP請求,,我們要使用另一個軟件叫做Postman,。這是一個API開發(fā)者和爬蟲工程師最常使用的工具之一。

首先在postman的官網(wǎng)下載:www.postman.com,。根據(jù)指示一步步安裝軟件,,中間沒有額外的設(shè)置。

打開postman后可以看到如下界面:

  1. 在最上面點(diǎn)擊加號,,可以添加一個新的請求
  2. 中間填寫請求的URL
  3. 點(diǎn)Headers進(jìn)入Headers的設(shè)置界面,,添加Header。

這些Header的名字和值可以在檢查器中復(fù)制過來,。如果自己拼寫,,注意千萬不要寫錯。

我們來了解一下幾個常見的header:

  • User-Agent: 這個Header表示請求者是誰,,一般是一個包括詳細(xì)版本信息的瀏覽器的名字,,比如:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36

    如果爬蟲不添加這個Header,服務(wù)器一下就能識別出這是不正常請求,,可以予以拒絕,。當(dāng)然,是否拒絕取決于程序員的代碼邏輯。

  • Cookie: 如果一個網(wǎng)站需要登錄,,登錄的信息就保存在Cookie中,。服務(wù)器通過這個Header判定是否登陸了,登陸的是誰,。

    假設(shè)我們要自動在京東商城下單,,我們可以先人工登錄,復(fù)制Cookie的值,,用Python發(fā)送請求并包含這個Cookie,,這樣服務(wù)器就認(rèn)為我們已經(jīng)登陸過了,允許我們下單或做其他操作,。如果在程序中加上計時的功能,,指定具體下單的時間點(diǎn),這就是秒殺程序,。這是爬取需要登錄的網(wǎng)站的一種常用方法,。

  • Accept:指瀏覽器接受什么格式的數(shù)據(jù),比如**application/json, text/plain, */***是指接受JSON,,文本數(shù)據(jù),,或者任何數(shù)據(jù)。

  • Origin-Domain: 是指請求者來自那個域名,,這個例子中是:www.

關(guān)于更多的HTTP的Header,,可以在網(wǎng)上搜索HTTP Headers學(xué)習(xí)。

我一個個添加常用的Header,,但服務(wù)器一直不返回數(shù)據(jù),,直到添加了Origin-Domain這個Header。這說明這個Header是必備條件,。

網(wǎng)頁的后臺程序有可能不檢查Header,,也有可能檢查一個Header,也有可能檢查多個Header,,這都需要我們嘗試才能知道,。

既然Origin-Domain是關(guān)鍵,也許后臺程序只檢查這一個Header,,我們通過左邊的選擇框去掉其他的Header,,只保留Origin-Domain,請求仍然成功,,這說明后臺只檢查了這一個Header:

然后修改地址欄中的page參數(shù),,獲取其他的頁,比如截圖中修改成了3,,再發(fā)送請求,,發(fā)現(xiàn)服務(wù)器返回了新的數(shù)據(jù)(其他的20本書),。這樣我們的請求過程就成功了。

4) 寫抓取程序

開發(fā)爬蟲,,主要的時間是分析,,一旦分析清楚了,爬取代碼并不復(fù)雜:

import requests

def get_page(page=1):
    '''抓取指定頁的數(shù)據(jù),,默認(rèn)是第1頁'''
    # 使用page動態(tài)拼接URL
    url = f'https://www./pubcloud/content/front/portal/getUbookList?page={page}&row=20&=&startPrice=&endPrice=&tagId='
    headers = {'Origin-Domain''www.'}
    # 請求的時候同時傳入headers
    res = requests.get(url, headers=headers) 
    print(res.text)

get_page(5)

這里我們測試了抓取第5頁的數(shù)據(jù),,比對打印出的JSON數(shù)據(jù)和網(wǎng)頁上的第5頁數(shù)據(jù),,結(jié)果是匹配的,。

現(xiàn)在我們?nèi)シ治鯦SON的數(shù)據(jù)結(jié)構(gòu),再來完善這個程序,。

5) 分析JSON數(shù)據(jù)

JSON就像Python中的字典,,用大括號存放數(shù)據(jù),用冒號分割鍵和值,。下面是省略的JSON數(shù)據(jù):

{
    'code''0',
    'data': {
        'current'1//第一頁
        'pages'144//一共幾頁
        'records': [  //很多本書的信息放在方括號中
            {
                'authors''[美] 史蒂芬·普拉達(dá)(Stephen Prata)',  //作者
                'code''UB7209840d845c9'//代碼
                'collectCount'416//喜歡數(shù)
                'commentCount'64//評論數(shù)
                'discountPrice'0//折扣價
                'downebookFlag''N',
                'fileType''',
                ...
            },
            {
                'authors''笨叔',
                'code''UB7263761464b35',
                'collectCount'21,
                'commentCount'3,
                'discountPrice'0,
                'downebookFlag''N',
                'fileType''',
                ...
            },
            ...
        ],
        'size'20,
        'total'2871
    },
    'msg''成功',
    'success'true
}

我們來學(xué)習(xí)一下這個JSON格式:

  1. 最外面是一個大括號,,里面包含了code, data, msg, success四塊信息。這個格式是開發(fā)這個網(wǎng)頁的程序員自己設(shè)計的,,不同的網(wǎng)頁可能不同,。
  2. 其中code, msg和sucess表示請求的狀態(tài)碼,請求返回的提示,,請求是否成功,。而真正的數(shù)據(jù)都在data中。
  3. data的冒號后面是一個大括號,,表示一個數(shù)據(jù)對象,。里面包含了當(dāng)前頁數(shù)(current),總頁數(shù)(pages),,書的信息(records)等,。
  4. records表示很多本書,所以它用一個方括號表示,,方括號里面又有很多大括號包起來的數(shù)據(jù)對象,,每個大括號表示一本書。
{
    'authors''[美] 史蒂芬·普拉達(dá)(Stephen Prata)'//書名
    'code''UB7209840d845c9'//代碼
    'collectCount'416//喜歡數(shù)
    'commentCount'64,  //評論數(shù)
    'discountPrice'0,  //折扣0,,表示沒有折扣
    ...
    'forSaleCount'3,  //在售數(shù)量
    ...
    'logo''https://cdn./pubcloud/bookImg/A20190961/20200701F892C57D.jpg',
    'name''C++ Primer Plus 第6版 中文版'//書名
    ...
    'price'100.30,  //價格
    ...
}

每本書的信息有很多個字段,,這里省略掉了很多字段,給重要的信息添加了注釋,。

6) 完成程序

現(xiàn)在來完善上面的程序,,從JSON中解析出我們要的數(shù)據(jù),為了簡化,,我們只抓?。簳?,作者,編號和價格,。

程序框架:

import requests
import json
import time 
class Book:
    # --省略--
def get_page(page=1):
    # --省略--
    books = parse_book(res.text)
    return books
def parse_book(json_text):
    #--省略--

all_books = []
for i in range(110):
    print(f'======抓取第{i}頁======')
    books = get_page(i)
    for b in books:
        print(b)
    all_books.extend(books)
    print('抓完一頁,,休息5秒鐘...')
    time.sleep(5)
  1. 定義了Book類來表示一本書
  2. 添加了parse_book函數(shù)負(fù)責(zé)解析數(shù)據(jù),返回包含當(dāng)前頁的20本書的list
  3. 最下面使用for循環(huán)抓取數(shù)據(jù),,并放到一個大的列表中,,range中添加要抓取的頁數(shù)。通過前面的分析可以知道一共有幾頁,。
  4. 抓取完一頁后,,一定要sleep幾秒,一是防止給網(wǎng)站帶來太大壓力,,二是防止網(wǎng)站會封鎖你的IP,,是為他好,也是為了自己好,。
  5. 把抓來的信息保存到文件中的代碼,,請自行完成。

下面來看看,,被省略掉的部分:

Book類:

class Book:
    def __init__(self, name, code, author, price):
        self.name = name
        self.code = code
        self.author = author
        self.price = price

    def __str__(self):
        return f'書名:{self.name},,作者:{self.author},價格:{self.price},,編號:{self.code}'

下面是__str__函數(shù)是一個魔法函數(shù),,當(dāng)我們使用print打印一個Book對象的時候,Python會自動調(diào)用這個函數(shù),。

parse_book函數(shù):

import json

def parse_book(json_text):
    '''根據(jù)返回的JSON字符串,,解析書的列表'''
    books = []
    # 把JSON字符串轉(zhuǎn)成一個字典dict類
    book_json = json.loads(json_text)
    records = book_json['data']['records']
    for r in records:
        author = r['authors']
        name = r['name']
        code = r['code']
        price = r['price']
        book = Book(name, code, author, price)
        books.append(book)
    return books
  1. 在最上面import了json模塊,這是Python自帶的,,不用安裝
  2. 關(guān)鍵的代碼就是使用json把抓來的JSON字符串轉(zhuǎn)成字典,,剩下的是對字典的操作,就很容易理解了,。

抓取基于JavaScript的網(wǎng)頁,,復(fù)雜主要在于分析過程,一旦分析完成了,,抓取的代碼比HTML的頁面還要更簡單清爽,。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多