亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

Python爬蟲(chóng)神器pyppeteer,對(duì) js 加密降維打擊

Karuru / 2596人閱讀

摘要:爬蟲(chóng)神器,對(duì)加密降維打擊是對(duì)無(wú)頭瀏覽器的封裝。使用等其他無(wú)頭瀏覽器的最大優(yōu)勢(shì)當(dāng)然是對(duì)加密實(shí)行降維打擊,完全無(wú)視加密手段,對(duì)于一些需要登錄的應(yīng)用,也可以模擬點(diǎn)擊然后保存。請(qǐng)求過(guò)濾你的那一段頁(yè)面自動(dòng)下拉腳本

爬蟲(chóng)神器pyppeteer,對(duì) js 加密降維打擊

pyppeteer?是對(duì)無(wú)頭瀏覽器?puppeteer的 Python 封裝。無(wú)頭瀏覽器廣泛用于自動(dòng)化測(cè)試,同時(shí)也是一種很好地爬蟲(chóng)思路。

使用 puppeteer(等其他無(wú)頭瀏覽器)的最大優(yōu)勢(shì)當(dāng)然是對(duì) js 加密實(shí)行降維打擊,完全無(wú)視 js 加密手段,對(duì)于一些需要登錄的應(yīng)用,也可以模擬點(diǎn)擊然后保存 cookie。而很多時(shí)候前端的加密是爬蟲(chóng)最難攻克的一部分。當(dāng)然puppeteer也有劣勢(shì),最大的劣勢(shì)就是相比面向接口爬蟲(chóng)效率很低,就算是無(wú)頭的chromium,那也會(huì)占用相當(dāng)一部分內(nèi)存。另外額外維護(hù)一個(gè)瀏覽器的啟動(dòng)、關(guān)閉也是一種負(fù)擔(dān)。

這篇文章我們來(lái)寫(xiě)一個(gè)簡(jiǎn)單的 demo,爬取拼多多搜索頁(yè)面的數(shù)據(jù),最終的效果如下:

我們把所有 api 請(qǐng)求的原始數(shù)據(jù)保存下來(lái):

示例 json 文件如下:

開(kāi)發(fā)環(huán)境

python3.6+

最好是 python3.7,因?yàn)?b>asyncio在 py3.7中加入了很好用的asyncio.run()方法。

安裝pyppeteer

如果安裝有問(wèn)題請(qǐng)去看官方文檔。

python3 -m pip install pyppeteer

安裝 chromium

你懂的,天朝網(wǎng)絡(luò)環(huán)境很復(fù)雜,如果要用pyppeteer自己綁定的chromium,半天都下載不下來(lái),所以我們要手動(dòng)安裝,然后在程序里面指定executablePath。

下載地址:www.chromium.org/getting-inv…

hello world

pyppeteer?的 hello world 程序是前往exmaple.com截個(gè)圖:

import asyncio
from pyppeteer import launch

async def main():
    browser = await launch({
        # Windows 和 Linux 的目錄不一樣,情換成自己對(duì)應(yīng)的executable文件地址
        "executablePath": "你下載的Chromium.app/Contents/MacOS/Chromium",
    })
    page = await browser.newPage()
    await page.goto("http://example.com")
    await page.screenshot({"path": "example.png"})
    await browser.close()

asyncio.get_event_loop().run_until_complete(main())
pyppeteer 重要接口介紹 pyppeteer.launch

launch 瀏覽器,可以傳入一個(gè)字典來(lái)配置幾個(gè)options,比如:

browser = await pyppeteer.launch({
    "headless": False, # 關(guān)閉無(wú)頭模式
    "devtools": True, # 打開(kāi) chromium 的 devtools
    "executablePath": "你下載的Chromium.app/Contents/MacOS/Chromiu",
    "args": [ 
        "--disable-extensions",
        "--hide-scrollbars",
        "--disable-bundled-ppapi-flash",
        "--mute-audio",
        "--no-sandbox",
        "--disable-setuid-sandbox",
        "--disable-gpu",
    ],
    "dumpio": True,  
})

其中所有可選的args參數(shù)在這里:peter.sh/experiments…

dumpio的作用:把無(wú)頭瀏覽器進(jìn)程的 stderr 核 stdout pip 到主程序,也就是設(shè)置為 True 的話(huà),chromium console 的輸出就會(huì)在主程序中被打印出來(lái)。

注入 js 腳本

可以通過(guò)page.evaluate形式,例如:

await page.evaluate("""
    () =>{
        Object.defineProperties(navigator,{
            webdriver:{
            get: () => false
            }
        })
    }
""")
我們會(huì)看到這一步非常關(guān)鍵,因?yàn)?b>puppeteer出于政策考慮(這個(gè)詞用的不是很好,就是那個(gè)意思)會(huì)設(shè)置window.navigator.webdrivertrue,告訴網(wǎng)站我是一個(gè) webdriver 驅(qū)動(dòng)的瀏覽器。有些網(wǎng)站比較聰明(反爬措施做得比較好),就會(huì)通過(guò)這個(gè)來(lái)判斷對(duì)方是不是爬蟲(chóng)程序。

這等價(jià)于在 devtools 里面輸入那一段 js 代碼。

還可以加載一個(gè) js 文件:

await page.addScriptTag(path=path_to_your_js_file)

通過(guò)注入 js 腳本能完成很多很多有用的操作,比如自動(dòng)下拉頁(yè)面等。

截獲 request 和 response
await page.setRequestInterception(True)
page.on("request", intercept_request)
page.on("response", intercept_response)

intercept_requestintercept_response相當(dāng)于是注冊(cè)的兩個(gè)回調(diào)函數(shù),在瀏覽器發(fā)出請(qǐng)求和獲取到請(qǐng)求之前指向這兩個(gè)函數(shù)。

比如可以這樣禁止獲取圖片、多媒體資源和發(fā)起 websocket 請(qǐng)求:

async def intercept_request(req):
    """請(qǐng)求過(guò)濾"""
    if req.resourceType in ["image", "media", "eventsource", "websocket"]:
        await req.abort()
    else:
        await req.continue_()

然后每次獲取到請(qǐng)求之后將內(nèi)容打印出來(lái)(這里只打印了fetchxhr類(lèi)型response 的內(nèi)容):

async def intercept_response(res):
    resourceType = res.request.resourceType
    if resourceType in ["xhr", "fetch"]:
        resp = await res.text()
        print(resp)
大家在學(xué)python的時(shí)候肯定會(huì)遇到很多難題,以及對(duì)于新技術(shù)的追求,這里推薦一下我們的Python學(xué)習(xí)扣qun:784758214,這里是python學(xué)習(xí)者聚集地

一共有哪些resourceType,pyppeteer文檔里面有:

拼多多搜索爬蟲(chóng) 頁(yè)面自動(dòng)下拉

拼多多的搜索界面是一個(gè)無(wú)限下拉的頁(yè)面,我們希望能夠?qū)崿F(xiàn)無(wú)限下拉頁(yè)面,并且能夠控制程序提前退出,不然一直下拉也不好,我們可能并不需要那么多數(shù)據(jù)。

js 腳本

async () => {
    await new Promise((resolve, reject) => {

        // 允許下滑的最大高度,防止那種可以無(wú)限下拉的頁(yè)面無(wú)法結(jié)束
        const maxScrollHeight = null;

        // 控制下拉次數(shù)
        const maxScrollTimes = null;
        let currentScrollTimes = 0;

        // 記錄上一次scrollHeight,便于判斷此次下拉操作有沒(méi)有成功,從而提前結(jié)束下拉
        let scrollHeight = 0;

        // maxTries : 有時(shí)候無(wú)法下拉可能是網(wǎng)速的原因
        let maxTries = 5;
        let tried = 0;

        const timer = setInterval(() => {

            // 下拉失敗,提前退出
            // BUG : 如果網(wǎng)速慢的話(huà),這一步會(huì)成立~
            // 所以設(shè)置一個(gè) maxTried 變量
            if (document.body.scrollHeight === scrollHeight) {
                tried += 1;
                if (tried >= maxTries) {
                    console.log("reached the end, now finished!");
                    clearInterval(timer);
                    resolve();
                }
            }

            scrollHeight = document.body.scrollHeight;
            window.scrollTo(0, scrollHeight);
            window.scrollBy(0, -10);

            // 判斷是否設(shè)置了maxScrollTimes
            if (maxScrollTimes) {
                if (currentScrollTimes >= maxScrollTimes) {
                    clearInterval(timer);
                    resolve();
                }
            }

            // 判斷是否設(shè)置了maxScrollHeight
            if (maxScrollHeight) {
                if (scrollHeight >= maxScrollHeight) {
                    if (currentScrollTimes >= maxScrollTimes) {
                        clearInterval(timer);
                        resolve();
                    }
                }
            }

            currentScrollTimes += 1;
            // 還原 tried
            tried = 0;
        }, 1000);

    });
};

這里面有幾個(gè)重要的參數(shù):

interval : 下拉間隔時(shí)間,以毫秒為單位

maxScrollHeight : 運(yùn)行頁(yè)面下拉最大高度

maxScrollTimes : 最多下拉多少次(推薦使用,可以更好控制爬取多少數(shù)據(jù))

maxTries : 下拉不成功時(shí)最多重試幾次,比如有時(shí)候會(huì)因?yàn)榫W(wǎng)絡(luò)原因?qū)е聸](méi)能在 interval ms 內(nèi)成功下拉

把這些替換成你需要的。同時(shí)你可以打開(kāi) chrome 的開(kāi)發(fā)者工具運(yùn)行一下這段 js 腳本。

完整代碼

這段代碼一共也就只有70多行,比較簡(jiǎn)陋,情根據(jù)自己的實(shí)際需求更改。

import os
import time
import json
from urllib.parse import urlsplit
import asyncio
import pyppeteer
from scripts import scripts

BASE_DIR = os.path.dirname(__file__)

async def intercept_request(req):
    """請(qǐng)求過(guò)濾"""
    if req.resourceType in ["image", "media", "eventsource", "websocket"]:
        await req.abort()
    else:
        await req.continue_()

async def intercept_response(res):
    resourceType = res.request.resourceType
    if resourceType in ["xhr", "fetch"]:
        resp = await res.text()

        url = res.url
        tokens = urlsplit(url)

        folder = BASE_DIR + "/" + "data/" + tokens.netloc + tokens.path + "/"
        if not os.path.exists(folder):
            os.makedirs(folder, exist_ok=True)
        filename = os.path.join(folder, str(int(time.time())) + ".json")
        with open(filename, "w", encoding="utf-8") as f:
            f.write(resp)

async def main():
    browser = await pyppeteer.launch({
        # "headless": False,
        # "devtools": True
        "executablePath": "/Users/changjiang/apps/Chromium.app/Contents/MacOS/Chromium",
        "args": [
            "--disable-extensions",
            "--hide-scrollbars",
            "--disable-bundled-ppapi-flash",
            "--mute-audio",
            "--no-sandbox",
            "--disable-setuid-sandbox",
            "--disable-gpu",
        ],
        "dumpio": True,
    })
    page = await browser.newPage()

    await page.setRequestInterception(True)
    page.on("request", intercept_request)
    page.on("response", intercept_response)

    await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
                            "(KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299")
    await page.setViewport({"width": 1080, "height": 960})
    await page.goto("http://yangkeduo.com")
    await page.evaluate("""
            () =>{
                   Object.defineProperties(navigator,{
                     webdriver:{
                       get: () => false
                     }
                   })
            }
        """)
    await page.evaluate("你的那一段頁(yè)面自動(dòng)下拉 js 腳本")
    await browser.close()

if __name__ == "__main__":
    asyncio.run(main())

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/43958.html

相關(guān)文章

  • Google推出的爬蟲(chóng)神器Pyppeteer,神擋殺神,佛擋殺佛!

    摘要:注意,是叫做,不是。兩款瀏覽器同根同源,它們有著同樣的,但配色不同,由藍(lán)紅綠黃四種顏色組成,而由不同深度的藍(lán)色構(gòu)成。另外是基于的新特性實(shí)現(xiàn)的,所以它的一些執(zhí)行也支持異步操作,效率相對(duì)于來(lái)說(shuō)也提高了。是否響應(yīng)信號(hào),一般是命令,默認(rèn)是。 如果大家對(duì) Python 爬蟲(chóng)有所了解的話(huà),想必你應(yīng)該聽(tīng)說(shuō)過(guò) Selenium 這個(gè)庫(kù),這實(shí)際上是一個(gè)自動(dòng)化測(cè)試工具,現(xiàn)在已經(jīng)被廣泛用于網(wǎng)絡(luò)爬蟲(chóng)中來(lái)應(yīng)對(duì) ...

    Fundebug 評(píng)論0 收藏0
  • 首次公開(kāi),整理12年積累的博客收藏夾,零距離展示《收藏夾吃灰》系列博客

    摘要:時(shí)間永遠(yuǎn)都過(guò)得那么快,一晃從年注冊(cè),到現(xiàn)在已經(jīng)過(guò)去了年那些被我藏在收藏夾吃灰的文章,已經(jīng)太多了,是時(shí)候把他們整理一下了。那是因?yàn)槭詹貖A太亂,橡皮擦給設(shè)置私密了,不收拾不好看呀。 ...

    Harriet666 評(píng)論0 收藏0
  • Python學(xué)到什么程度才可以去找工作?掌握這4點(diǎn)足夠了!

    摘要:接下來(lái)我們就來(lái)看看學(xué)到什么程度才算是真正學(xué)會(huì)可以去一展身手。一確立目標(biāo)了解需求做什么事情都要先確定好目標(biāo),才不至于迷失方向。 大家在學(xué)習(xí)Python的時(shí)候,有人會(huì)問(wèn)Python要學(xué)到什么程度才能出去找工作,對(duì)于在Python培訓(xùn)機(jī)構(gòu)學(xué)習(xí)Python的同學(xué)來(lái)說(shuō)這都不是問(wèn)題,因?yàn)榘凑誔ython課程大綱來(lái),一般都不會(huì)有什么問(wèn)題,而對(duì)于自學(xué)Python來(lái)說(shuō),那就比較難掌握,冒然出去找工作非常...

    Yuqi 評(píng)論0 收藏0
  • Python爬蟲(chóng)偷懶神器 —— 一鍵構(gòu)造請(qǐng)求頭

    摘要:但是手動(dòng)復(fù)制粘貼字典里的每一個(gè)鍵值對(duì)太費(fèi)事了一個(gè)不那么方便的解決方案用正則表達(dá)式或者直接字符串替換,把字符串直接轉(zhuǎn)化為字典,封裝成函數(shù)方便以后反復(fù)調(diào)用。有的人喜歡用這種方法,每次復(fù)制信息,然后調(diào)用自己封裝好的函數(shù),但我覺(jué)得還是挺麻煩的。 今天介紹個(gè)神奇的網(wǎng)站!堪稱(chēng)爬蟲(chóng)偷懶的神器! 我們?cè)趯?xiě)爬蟲(chóng),構(gòu)建網(wǎng)絡(luò)請(qǐng)求的時(shí)候,不可避免地要添加請(qǐng)求頭( headers ),以 mdn 學(xué)習(xí)區(qū)為例,我...

    charles_paul 評(píng)論0 收藏0
  • Python爬蟲(chóng):通過(guò)做項(xiàng)目,小編了解了酷狗音樂(lè)的加密過(guò)程

    摘要:獲取音樂(lè)播放列表其實(shí),這就是小編要講的重點(diǎn),因?yàn)榫褪沁@部分用到了加密。 1.前言 小編在這里講一下,下面的內(nèi)容僅供學(xué)習(xí)參考,切莫用于商業(yè)活動(dòng),一經(jīng)被相關(guān)人員發(fā)現(xiàn),本...

    張憲坤 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<