一個優(yōu)秀的爬蟲框架應(yīng)該什么樣?go-crawler

基于golang實(shí)現(xiàn)的爬蟲框架,編寫簡單,性能強(qiáng)勁,內(nèi)置了豐富的實(shí)用中間件,支持多種解析、保存方式。

go-crawler

Feature

  • 編寫簡單,性能強(qiáng)勁。
  • 內(nèi)置多種實(shí)用中間件,開發(fā)起來更輕松。
  • 支持多種解析方式,解析頁面更簡單。
  • 支持多種保存方式,數(shù)據(jù)存儲更靈活。
  • 提供了豐富的配置選項(xiàng),配置更自由。
  • 組件支持自定義,擴(kuò)展功能更簡單。
  • 內(nèi)置開發(fā)服務(wù),調(diào)試開發(fā)更方便。

Usage

  • 基本架構(gòu)

    • Spider:在Spider里可以發(fā)起請求和解析內(nèi)容。您需要使用spider.SetName(name)方法為每個Spider設(shè)置一個唯一名稱。
    • BaseSpider:BaseSpider實(shí)現(xiàn)了Spider的公共方法,避免了在每個Spider中重復(fù)編寫相同的代碼。
    • Crawler:Crawler集成了Spider、Downloader(下載器)、Exporter(導(dǎo)出器)、Scheduler(調(diào)度器)等組件,是爬蟲的邏輯處理中心。
  • crawler選項(xiàng)。

    • WithMode 設(shè)置模式(Mode)。
    • WithPlatforms 設(shè)置瀏覽器平臺(Platforms)。
    • WithBrowsers 設(shè)置瀏覽器(Browsers)。
    • WithLogger 設(shè)置日志(Logger)。
    • WithFilter 設(shè)置過濾器(Filter)。
    • WithDownloader 設(shè)置下載器(Downloader)。
    • WithExporter 設(shè)置導(dǎo)出器(Exporter)。
    • WithMiddleware 設(shè)置中間件(Middleware)。
    • WithStatsMiddleware 設(shè)置統(tǒng)計中間件,用于記錄和統(tǒng)計爬蟲的性能和運(yùn)行情況。
    • WithDumpMiddleware 設(shè)置打印中間件。
    • WithProxyMiddleware 設(shè)置代理中間件,用于使用代理服務(wù)器進(jìn)行爬取。
    • WithRobotsTxtMiddleware 設(shè)置開啟robots.txt支持中間件,用于遵守網(wǎng)站的 robots.txt 規(guī)則。
    • WithFilterMiddleware 設(shè)置過濾器中間件,用于過濾已處理的請求。
    • WithFileMiddleware 設(shè)置文件中間件,用于處理文件下載請求。
    • WithImageMiddleware 設(shè)置圖像中間件,用于處理圖像下載請求。
    • WithHttpMiddleware 設(shè)置 HTTP 中間件。
    • WithRetryMiddleware 設(shè)置重試中間件,用于在請求失敗時進(jìn)行自動重試。
    • WithUrlMiddleware 設(shè)置 URL 中間件。
    • WithReferrerMiddleware 設(shè)置 Referrer 中間件,用于自動設(shè)置請求的 Referrer 頭。
    • WithCookieMiddleware 設(shè)置 Cookie 中間件,用于處理請求和響應(yīng)中的 Cookie,自動在接下來的請求設(shè)置之前的 Cookie。
    • WithRedirectMiddleware 設(shè)置重定向中間件,用于自動處理請求的重定向,跟隨重定向鏈接并獲取最終響應(yīng)。
    • WithChromeMiddleware 設(shè)置 Chrome 中間件,用于模擬 Chrome 瀏覽器。
    • WithHttpAuthMiddleware 設(shè)置開啟HTTP認(rèn)證中間件,用于處理需要認(rèn)證的網(wǎng)站。
    • WithCompressMiddleware 設(shè)置壓縮中間件,用于處理請求和響應(yīng)的壓縮。當(dāng)爬蟲發(fā)送請求或接收響應(yīng)時,該中間件可以自動處理壓縮算法,解壓縮請求或響應(yīng)的內(nèi)容。
    • WithDecodeMiddleware 設(shè)置解碼中間件,用于處理請求和響應(yīng)的解碼操作。該中間件可以處理請求或響應(yīng)中的編碼內(nèi)容。
    • WithDeviceMiddleware 設(shè)置開啟設(shè)備模擬中間件
    • WithCustomMiddleware 設(shè)置自定義中間件,允許用戶定義自己的中間件組件。
    • WithPipeline 設(shè)置Pipeline,用于處理爬取的數(shù)據(jù)并進(jìn)行后續(xù)操作。
    • WithDumpPipeline 設(shè)置打印管道。
    • WithFilePipeline 設(shè)置文件管道,用于處理爬取的文件數(shù)據(jù),將文件保存到指定位置。
    • WithImagePipeline 設(shè)置圖像管道,用于處理爬取的圖像數(shù)據(jù),將保存圖像到指定位置。
    • WithFilterPipeline 設(shè)置過濾器管道,用于過濾爬取過的數(shù)據(jù)。
    • WithCsvPipeline 設(shè)置 CSV 數(shù)據(jù)處理管道,將爬取的數(shù)據(jù)保存為 CSV 格式。
    • WithJsonLinesPipeline 設(shè)置 JSON Lines 數(shù)據(jù)處理管道,將爬取的數(shù)據(jù)保存為 JSON Lines 格式。
    • WithMongoPipeline 設(shè)置 MongoDB 數(shù)據(jù)處理管道,將爬取的數(shù)據(jù)保存到 MongoDB 數(shù)據(jù)庫。
    • WithMysqlPipeline 設(shè)置 MySQL 數(shù)據(jù)處理管道,將爬取的數(shù)據(jù)保存到 MySQL 數(shù)據(jù)庫。
    • WithKafkaPipeline 設(shè)置 Kafka 數(shù)據(jù)處理管道,將爬取的數(shù)據(jù)發(fā)送到 Kafka 消息隊(duì)列。
    • WithCustomPipeline 設(shè)置自定義數(shù)據(jù)處理管道。
    • WithRetryMaxTimes 設(shè)置請求的最大重試次數(shù)(RetryMaxTimes)。
    • WithTimeout 設(shè)置請求的超時時間(Timeout)。
    • WithInterval 設(shè)置請求的間隔時間(Interval)。
    • WithOkHttpCodes 設(shè)置正常的HTTP狀態(tài)碼(OkHttpCodes)。
  • Item

    Item用于存儲需要導(dǎo)出的數(shù)據(jù)和一些其他輔助信息。
    框架里內(nèi)置的Item涵蓋了主要文件、數(shù)據(jù)庫、消息隊(duì)列等存儲方式。
    pkg.Item是一個接口,不能直接使用。pkg.ItemUnimplemented實(shí)現(xiàn)了pkg.Item的所有方法。
    如果Item需要實(shí)現(xiàn)pkg.Item,可以組合pkg.ItemUnimplemented。 如:

    type ItemNone struct {
        pkg.ItemUnimplemented
    }
    
    
    • Item有一些通用方法:
      • GetName() pkg.ItemName
        獲取Item的具體類型,如pkg.ItemNone、pkg.ItemCsv、pkg.ItemJsonl、pkg.ItemMongo、pkg.ItemMysql、pkg.ItemKafka等,用于Item反序列化到具體Item實(shí)現(xiàn)。
      • SetReferrer(string) 設(shè)置referrer,可以用于記錄請求的來源,一般不需要自己設(shè)置,由ReferrerMiddleware自動設(shè)置。
      • GetReferrer() string 獲取referrer。
      • SetUniqueKey(string) 設(shè)置uniqueKey,可以用于過濾和其他唯一用途。
      • GetUniqueKey() string 獲取uniqueKey。
      • SetId(any) 設(shè)置id,主要用于保存數(shù)據(jù)時的主鍵,和uniqueKey的一個區(qū)別是,id可能是在Response中產(chǎn)生,請求時不一定能獲得。
      • GetId() any 獲取id。
      • SetData(any) 設(shè)置data,這是要存儲的完整數(shù)據(jù)。為了規(guī)范化,強(qiáng)制要求指針類型。存儲到不同的目標(biāo)時,data需要設(shè)置不同的格式。
      • GetData() any 獲取data。
      • SetFilesRequest([]pkg.Request) 設(shè)置文件的請求。這是一個slice,可以下載多個文件。
      • GetFilesRequest() []pkg.Request 獲取文件的請求。
      • SetFiles([]pkg.File) 設(shè)置文件。下載后的文件通過這個方法設(shè)置到Item中。
      • GetFiles() []pkg.File 獲取文件。
      • SetImagesRequest([]pkg.Request) 設(shè)置圖片的請求。這是一個slice,可以下載多個圖片。
      • GetImagesRequest() []pkg.Request 獲取圖片的請求。
      • SetImages([]pkg.Image) 設(shè)置圖片。下載后的圖片通過這個方法設(shè)置到Item中。
      • GetImages() []pkg.Image 獲取圖片。
    • 內(nèi)置Item實(shí)現(xiàn):框架提供了一些內(nèi)置的Item實(shí)現(xiàn),如pkg.ItemNone、pkg.ItemCsv、pkg.ItemJsonl、pkg.ItemMongo、pkg.ItemMysql、pkg.ItemKafka等。
      您可以根據(jù)需要,返回Item,并開啟相應(yīng)的Pipeline。如:
      err = s.YieldItem(ctx, items.NewItemMongo(s.collection, true).
      SetUniqueKey(extra.Keyword).
      SetId(extra.Keyword).
      SetData(&data))
      
      
      app.NewApp(NewSpider,
      pkg.WithMongoPipeline(),
      ).Run()
      
      
      • pkg.ItemNone 這個Item沒有實(shí)現(xiàn)任何其他方法,主要用于調(diào)試。
        • items.NewItemNone()
      • pkg.ItemCsv 保存到csv中。
        • items.NewItemCsv(filename string)
        • filename 存儲的文件名,不包括拓展名
      • pkg.ItemJsonl 保存到j(luò)sonl中。
        • items.NewItemJsonl(filename string)
        • filename 存儲的文件名,不包括拓展名
      • pkg.ItemMongo 保存到mongo中。
        • items.NewItemMongo(collection string, update bool)
        • collection mongo collection
        • update 如果數(shù)據(jù)已存在mongo中,是否更新
      • pkg.ItemMysql 保存到mysql中。
        • items.NewItemMysql(table string, update bool)
        • table mysql table
        • update 如果數(shù)據(jù)已存在mongo中,是否更新
      • pkg.ItemKafka 保存到kafka中。
        • items.NewItemKafka(topic string)
        • topic kafka topic
  • middleware/pipeline包括框架內(nèi)置、公共自定義(internal/middlewares,internal/pipelines)和爬蟲內(nèi)自定義(和爬蟲同module)。

  • 請確保不同中間件和Pipeline的order值不重復(fù)。如果有重復(fù)的order值,后面的中間件或Pipeline將替換前面的中間件或Pipeline。

  • 在框架中,內(nèi)置的中間件具有預(yù)定義的order值,這些order值是10的倍數(shù),例如10、20、30等。
    為了避免與內(nèi)置中間件的order沖突,建議自定義中間件時選擇不同的order值。
    當(dāng)您自定義中間件時,請選擇避開內(nèi)置中間件的order值。
    根據(jù)中間件的功能和需求,按照預(yù)期的執(zhí)行順序進(jìn)行配置。確保較低order值的中間件先執(zhí)行,然后依次執(zhí)行較高order值的中間件。
    內(nèi)置的中間件和自定義中間件使用默認(rèn)的order值即可。
    如果需要改變默認(rèn)的order值,需要在NewApp中加入crawler選項(xiàng)pkg.WithMiddleware(new(middleware), order)啟用該中間件并應(yīng)用該order值。

    • custom: 10
      • 自定義中間件
      • 在NewApp中加入crawler選項(xiàng)pkg.WithCustomMiddleware(new(CustomMiddleware))啟用該中間件。
    • dump: 20
      • 控制臺打印item.data中間件,用于打印請求和響應(yīng)的詳細(xì)信息。
      • 可以通過配置項(xiàng)enable_dump_middleware來啟用或禁用,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithDumpMiddleware()
    • proxy: 30
      • 用于切換請求使用的代理。
      • 可以通過配置項(xiàng)enable_proxy_middleware來啟用或禁用,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithProxyMiddleware()
    • robotsTxt: 40
      • robots.txt支持中間件,用于支持爬取網(wǎng)站的robots.txt文件。
      • 可以通過配置項(xiàng)enable_robots_txt_middleware來啟用或禁用,默認(rèn)禁用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithRobotsTxtMiddleware()
    • filter: 50
      • 過濾重復(fù)請求中間件,用于過濾重復(fù)的請求。默認(rèn)只有在Item保存成功后才會進(jìn)入去重隊(duì)列。
      • 可以通過配置項(xiàng)enable_filter_middleware來啟用或禁用,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithFilterMiddleware()
    • file: 60
      • 自動添加文件信息中間件,用于自動添加文件信息到請求中。
      • 可以通過配置項(xiàng)enable_file_middleware來啟用或禁用,默認(rèn)禁用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithFileMiddleware()
    • image: 70
      • 自動添加圖片的寬高等信息中間件
      • 用于自動添加圖片信息到請求中??梢酝ㄟ^配置項(xiàng)enable_image_middleware來啟用或禁用,默認(rèn)禁用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithImageMiddleware()
    • retry: 80
      • 請求重試中間件,用于在請求失敗時進(jìn)行重試。
      • 默認(rèn)最大重試次數(shù)為10??梢酝ㄟ^配置項(xiàng)enable_retry_middleware來啟用或禁用,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithRetryMiddleware()
    • url: 90
      • 限制URL長度中間件,用于限制請求的URL長度。
      • 可以通過配置項(xiàng)enable_url_middleware和url_length_limit來啟用和設(shè)置最長URL長度,默認(rèn)啟用和最長長度為2083。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithUrlMiddleware()
    • referrer: 100
      • 自動添加Referrer中間件,用于自動添加Referrer到請求中。
      • 可以根據(jù)referrer_policy配置項(xiàng)選擇不同的Referrer策略,DefaultReferrerPolicy會加入請求來源,NoReferrerPolicy不加入請求來源
      • 配置 enable_referrer_middleware: true 是否開啟自動添加referrer,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithReferrerMiddleware()
    • cookie: 110
      • 自動添加Cookie中間件,用于自動添加之前請求返回的Cookie到后續(xù)請求中。
      • 可以通過配置項(xiàng)enable_cookie_middleware來啟用或禁用,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithCookieMiddleware()
    • redirect: 120
      • 網(wǎng)址重定向中間件,用于處理網(wǎng)址重定向,默認(rèn)支持301和302重定向。
      • 可以通過配置項(xiàng)enable_redirect_middleware和redirect_max_times來啟用和設(shè)置最大重定向次數(shù),默認(rèn)啟用和最大次數(shù)為1。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithRedirectMiddleware()
    • chrome: 130
      • 模擬Chrome中間件,用于模擬Chrome瀏覽器。
      • 可以通過配置項(xiàng)enable_chrome_middleware來啟用或禁用,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithChromeMiddleware()
    • httpAuth: 140
      • HTTP認(rèn)證中間件,通過提供用戶名(username)和密碼(password)進(jìn)行HTTP認(rèn)證。
      • 需要在具體的請求中設(shè)置用戶名和密碼??梢酝ㄟ^配置項(xiàng)enable_http_auth_middleware來啟用或禁用,默認(rèn)禁用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithHttpAuthMiddleware()
    • compress: 150
      • 支持gzip/deflate解壓縮中間件,用于處理響應(yīng)的壓縮編碼。
      • 可以通過配置項(xiàng)enable_compress_middleware來啟用或禁用,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithCompressMiddleware()
    • decode: 160
      • 中文解碼中間件,支持對響應(yīng)中的GBK、GB2312和Big5編碼進(jìn)行解碼。
      • 可以通過配置項(xiàng)enable_decode_middleware來啟用或禁用,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithDecodeMiddleware()
    • device: 170
      • 修改請求設(shè)備信息中間件,用于修改請求的設(shè)備信息,包括請求頭(header)和TLS信息。目前只支持User-Agent隨機(jī)切換。
      • 需要設(shè)置設(shè)備范圍(Platforms)和瀏覽器范圍(Browsers)。
      • Platforms: Windows/Mac/Android/Iphone/Ipad/Linux
      • Browsers: Chrome/Edge/Safari/FireFox
      • 可以通過配置項(xiàng)enable_device_middleware來啟用或禁用,默認(rèn)禁用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithDeviceMiddleware()啟用該中間件。
    • http: 200
      • 創(chuàng)建請求中間件,用于創(chuàng)建HTTP請求。
      • 可以通過配置項(xiàng)enable_http_middleware來啟用或禁用,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithHttpMiddleware()
    • stats: 210
      • 數(shù)據(jù)統(tǒng)計中間件,用于統(tǒng)計爬蟲的請求、響應(yīng)和處理情況。
      • 可以通過配置項(xiàng)enable_stats_middleware來啟用或禁用,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithStatsMiddleware()
  • Pipeline用于流式處理Item,如數(shù)據(jù)過濾、數(shù)據(jù)存儲等。
    通過配置不同的Pipeline,您可以方便地處理Item并將結(jié)果保存到不同的目標(biāo),如控制臺、文件、數(shù)據(jù)庫或消息隊(duì)列中。
    內(nèi)置的Pipeline和自定義Pipeline使用默認(rèn)的order值即可。
    如果需要改變默認(rèn)的order值,需要在NewApp中加入crawler選項(xiàng)pkg.WithPipeline(new(pipeline), order)啟用該P(yáng)ipeline并應(yīng)用該order值。

    • dump: 10
      • 用于在控制臺打印Item的詳細(xì)信息。
      • 您可以通過配置enable_dump_pipeline來控制是否啟用該P(yáng)ipeline,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithDumpPipeline()啟用該P(yáng)ipeline。
    • file: 20
      • 用于下載文件并保存到Item中。
      • 您可以通過配置enable_file_pipeline來控制是否啟用該P(yáng)ipeline,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithFilePipeline()啟用該P(yáng)ipeline。
    • image: 30
      • 用于下載圖片并保存到Item中。
      • 您可以通過配置enable_image_pipeline來控制是否啟用該P(yáng)ipeline,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithImagePipeline()啟用該P(yáng)ipeline。
    • filter: 200
      • 用于對Item進(jìn)行過濾。
      • 它可用于去重請求,需要在中間件同時啟用filter。
      • 默認(rèn)情況下,Item只有在成功保存后才會進(jìn)入去重隊(duì)列。
      • 您可以通過配置enable_filter_pipeline來控制是否啟用該P(yáng)ipeline,默認(rèn)啟用。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithFilterPipeline()啟用該P(yáng)ipeline。
    • csv: 101
      • 用于將結(jié)果保存到CSV文件中。
      • 需要在ItemCsv中設(shè)置FileName,指定保存的文件名稱(不包含.csv擴(kuò)展名)。
      • 您可以使用tag column:""來定義CSV文件的列名。
      • 您可以通過配置enable_csv_pipeline來控制是否啟用該P(yáng)ipeline,默認(rèn)關(guān)閉。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithCsvPipeline()啟用該P(yáng)ipeline。
    • jsonLines: 102
      • 用于將結(jié)果保存到JSON Lines文件中。
      • 需要在ItemJsonl中設(shè)置FileName,指定保存的文件名稱(不包含.jsonl擴(kuò)展名)。
      • 您可以使用tag json:""來定義JSON Lines文件的字段。
      • 您可以通過配置enable_json_lines_pipeline來控制是否啟用該P(yáng)ipeline,默認(rèn)關(guān)閉。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithJsonLinesPipeline()啟用該P(yáng)ipeline。
    • mongo: 103
      • 用于將結(jié)果保存到MongoDB中。
      • 需要在ItemMongo中設(shè)置Collection,指定保存的collection名稱。
      • 您可以使用tag bson:""來定義MongoDB文檔的字段。
      • 您可以通過配置enable_mongo_pipeline來控制是否啟用該P(yáng)ipeline,默認(rèn)關(guān)閉。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithMongoPipeline()啟用該P(yáng)ipeline。
    • mysql: 104
      • 用于將結(jié)果保存到MySQL中。
      • 需要在ItemMysql中設(shè)置Table,指定保存的表名。
      • 您可以使用tag column:""來定義MySQL表的列名。
      • 您可以通過配置enable_mysql_pipeline來控制是否啟用該P(yáng)ipeline,默認(rèn)關(guān)閉。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithMysqlPipeline()啟用該P(yáng)ipeline。
    • kafka: 105
      • 用于將結(jié)果保存到Kafka中。
      • 需要在ItemKafka中設(shè)置Topic,指定保存的主題名。
      • 您可以使用tag json:""來定義Kafka消息的字段。
      • 您可以通過配置enable_kafka_pipeline來控制是否啟用該P(yáng)ipeline,默認(rèn)關(guān)閉。
      • 在NewApp中加入crawler選項(xiàng)pkg.WithKafkaPipeline()啟用該P(yáng)ipeline。
    • custom: 110
      • 自定義pipeline
      • 在NewApp中加入crawler選項(xiàng)pkg.WithCustomPipeline(new(CustomPipeline))啟用該P(yáng)ipeline。
  • 信號(Signal)是一種機(jī)制,用于在運(yùn)行時處理外部發(fā)出的操作指令。通過捕獲和處理信號,您可以實(shí)現(xiàn)對爬蟲的控制和管理

  • 在配置文件中配置全局的請求參數(shù),并在具體的請求中可以覆蓋這些全局配置,可以提供更靈活和細(xì)粒度的請求定制

  • 框架內(nèi)置了多個解析模塊。這些解析模塊提供了不同的選擇器和語法,以適應(yīng)不同的數(shù)據(jù)提取需求。您可以根據(jù)具體的爬蟲任務(wù)和數(shù)據(jù)結(jié)構(gòu),選擇適合您的解析模塊和語法,從網(wǎng)頁響應(yīng)中準(zhǔn)確地提取所需的數(shù)據(jù)。

    • query選擇器 go-query是一個處理query選擇器的庫 go-query
      • 通過調(diào)用response.Query()方法,您可以使用query選擇器語法來從HTML或XML響應(yīng)中提取數(shù)據(jù)。
    • xpath選擇器 go-xpath是一個可用于XPath選擇的庫 go-xpath
      • 通過調(diào)用response.Xpath()方法,您可以使用XPath表達(dá)式來從HTML或XML響應(yīng)中提取數(shù)據(jù)。
    • gjson gjson是一個用于處理JSON的庫
      • 通過調(diào)用response.Json()方法,您可以使用gjson語法從JSON響應(yīng)中提取數(shù)據(jù)。
    • re選擇器 go-re是一個處理正則的庫 go-re
      • 通過調(diào)用response.Re()方法,您可以使用正則表達(dá)式從響應(yīng)中提取數(shù)據(jù)。
  • 代理。它可以幫助爬蟲在請求網(wǎng)站時隱藏真實(shí)IP地址。

    • 自行搭建隧道代理:您可以使用 go-proxy
      等工具來搭建隧道代理。這些代理工具可以提供隨機(jī)切換的代理功能,對調(diào)用方無感知,方便使用。
      您可以在爬蟲框架中集成這些代理工具,以便在爬蟲請求時自動切換代理。
      這是一個隨機(jī)切換的隧道代理,調(diào)用方無感知,方便使用。后期會加入一些其他的調(diào)用方式,比如維持原來的代理地址。
    • 其他調(diào)用方式:除了隨機(jī)切換的代理方式,后期可以考慮加入其他的調(diào)用方式。
      例如,保持原來的代理地址不變,或者使用其他代理池工具進(jìn)行代理IP的管理和調(diào)度。這樣可以提供更多靈活性和選擇性,以滿足不同的代理需求。
  • 要提高爬蟲的性能,您可以考慮關(guān)閉一些未使用的中間件或Pipeline,以減少不必要的處理和資源消耗。以下是一些建議:

    • 檢查中間件:審查已配置的中間件,并根據(jù)需要禁用不使用的中間件。您可以在配置文件中進(jìn)行修改,或者在爬蟲的入口方法中進(jìn)行相應(yīng)的配置更改。
    • 禁用不需要的Pipeline:檢查已配置的Pipeline,并禁用不需要的Pipeline。
      例如,如果您不需要保存結(jié)果到MongoDB,可以禁用MongoPipeline。
    • 評估性能影響:在禁用中間件或Pipeline之前,請?jiān)u估其對爬蟲性能的實(shí)際影響。確保禁用的部分不會對功能產(chǎn)生負(fù)面影響。
    • 可以禁用的配置:
      • enable_dump_middleware: false
      • enable_filter_middleware: false
      • enable_file_middleware: false
      • enable_image_middleware: false
      • enable_http_middleware: false
      • enable_retry_middleware: false
      • enable_referrer_middleware: false
      • enable_http_auth_middleware: false
      • enable_cookie_middleware: false
      • enable_url_middleware: false
      • enable_compress_middleware: false
      • enable_decode_middleware: false
      • enable_redirect_middleware: false
      • enable_chrome_middleware: false
      • enable_device_middleware: false
      • enable_proxy_middleware: false
      • enable_robots_txt_middleware: false
      • enable_stats_middleware: false
      • enable_dump_pipeline: false
      • enable_file_pipeline: false
      • enable_image_pipeline: false
      • enable_filter_pipeline: false
      • enable_csv_pipeline: false
      • enable_json_lines_pipeline: false
      • enable_mongo_pipeline: false
      • enable_mysql_pipeline: false
      • enable_kafka_pipeline: false
  • 文件下載

    • 如果您希望將文件保存到S3等對象存儲中,需要進(jìn)行相應(yīng)的配置
    • Files下載
      • 在Item中設(shè)置Files請求:在Item中,您需要設(shè)置Files請求,即包含要下載的文件的請求列表。
        可以使用item.SetFilesRequest([]pkg.Request{...})
        方法設(shè)置請求列表。
      • Item.data:您的Item.data字段需要實(shí)現(xiàn)pkg.File的切片,用于保存下載文件的結(jié)果。
        該字段的名稱必須是Files,如type DataFile struct {Files []*media.File}
    • Images下載
      • 在Item中設(shè)置Images請求:在Item中,您需要設(shè)置Images請求,即包含要下載的圖片的請求列表。
        可以使用item.SetImagesRequest([]pkg.Request{...})方法設(shè)置請求列表。
      • Item.data:您的Item.data字段需要實(shí)現(xiàn)pkg.Image的切片,用于保存下載圖片的結(jié)果。
        該字段的名稱必須是Images,如type DataImage struct {Images []*media.Image}。
  • 爬蟲結(jié)構(gòu)

    • 建議按照每個網(wǎng)站(子網(wǎng)站)或者每個業(yè)務(wù)為一個spider。不必分的太細(xì),也不必把所有的網(wǎng)站和業(yè)務(wù)都寫在一個spider里
  • 為了方便開發(fā)和調(diào)試,框架內(nèi)置了本地devServer,在-m dev模式下會默認(rèn)啟用。
    通過使用本地devServer,您可以在開發(fā)和調(diào)試過程中更方便地模擬和觀察網(wǎng)絡(luò)請求和響應(yīng),以及處理自定義路由邏輯。
    這為開發(fā)者提供了一個便捷的工具,有助于快速定位和解決問題。
    您可以自定義路由(route),只需要實(shí)現(xiàn)pkg.Route 接口,并通過在Spider中調(diào)用AddDevServerRoutes(...pkg.Route)
    方法將其注冊到devServer中。

    • 支持http和https,您可以通過設(shè)置dev_server選項(xiàng)來指定devServer的URL。
      http://localhost:8081表示使用HTTP協(xié)議,https://localhost:8081表示使用HTTPS協(xié)議。
    • 默認(rèn)顯示JA3指紋。JA3是一種用于TLS客戶端指紋識別的算法,它可以顯示與服務(wù)器建立連接時客戶端使用的TLS版本和加密套件等信息。
    • 您可以使用tls工具來生成服務(wù)器的私鑰和證書,以便在devServer中使用HTTPS。tls工具可以幫助您生成自簽名的證書,用于本地開發(fā)和測試環(huán)境。
    • devServer內(nèi)置了多種handler,這些handler提供了豐富的功能,可以模擬各種網(wǎng)絡(luò)情景,幫助進(jìn)行開發(fā)和調(diào)試。
      您可以根據(jù)需要選擇合適的handler,并將其配置到devServer中,以模擬特定的網(wǎng)絡(luò)響應(yīng)和行為。
      • BadGatewayHandler 模擬返回502狀態(tài)碼
      • Big5Handler 模擬使用big5編碼
      • CookieHandler 模擬返回cookie
      • DeflateHandler 模擬使用Deflate壓縮
      • FileHandler 模擬輸出文件
      • Gb2312Handler 模擬使用gb2312編碼
      • Gb18030Handler 模擬使用gb18030編碼
      • GbkHandler 模擬使用gbk編碼
      • GzipHandler 模擬使用gzip壓縮
      • HelloHandler 打印請求的header和body信息
      • HttpAuthHandler 模擬http-auth認(rèn)證
      • InternalServerErrorHandler 模擬返回500狀態(tài)碼
      • OkHandler 模擬正常輸出,返回200狀態(tài)碼
      • RateLimiterHandler 模擬速率限制,目前基于全部請求,不區(qū)分用戶??膳cHttpAuthHandler配合使用。
      • RedirectHandler 模擬302臨時跳轉(zhuǎn),需要同時啟用OkHandler
      • RobotsTxtHandler 返回robots.txt文件

args

通過配置環(huán)境變量和啟動參數(shù),您可以更靈活地配置和控制爬蟲的行為,包括選擇配置文件、指定入口方法、傳遞額外參數(shù)以及設(shè)定啟動模式。這樣的設(shè)計可以提高爬蟲的可配置性和可擴(kuò)展性,使得爬蟲框架更適應(yīng)各種不同的應(yīng)用場景。

  • CRAWLER_CONFIG_FILE -c 配置文件路徑,必須進(jìn)行配置。
  • CRAWLER_START_FUNC -f 入口方法名稱,默認(rèn)Test。
  • CRAWLER_ARGS -a 額外的參數(shù),該參數(shù)是非必須項(xiàng)。建議使用JSON字符串。參數(shù)會被入口方法調(diào)用。
  • CRAWLER_MODE -m 啟動模式,默認(rèn)test。您可以根據(jù)需要使用不同的模式,如dev、prod等,以區(qū)分開發(fā)和生產(chǎn)環(huán)境。

config

  • bot_name: crawler 項(xiàng)目名

數(shù)據(jù)庫配置:

  • mongo_enable: 是否啟用MongoDB。
  • mongo.example.uri: MongoDB的URI。
  • mongo.example.database: MongoDB的數(shù)據(jù)庫名稱。
  • mysql_enable: 是否啟用MySQL。
  • mysql.example.uri: MySQL的URI。
  • mysql.example.database: MySQL的數(shù)據(jù)庫名稱。
  • redis_enable: 是否啟用Redis。
  • redis.example.addr: Redis的地址。
  • redis.example.password: Redis的密碼。
  • redis.example.db: Redis的數(shù)據(jù)庫。
  • s3_enable: 是否啟用S3對象存儲(如COS、OSS、MinIO等)
  • s3.example.endpoint: S3的地址
  • s3.example.region: S3的區(qū)域。
  • s3.example.id: S3的ID。
  • s3.example.key: S3的密鑰。
  • s3.example.bucket: S3的桶名稱。
  • kafka_enable: 是否啟用Kafka。
  • kafka.example.uri: Kafka的URI。

日志配置:

  • log.filename: 日志文件路徑??梢允褂?{name}"的方式替換成-ldflags的參數(shù)。
  • log.long_file: 如果設(shè)置為true(默認(rèn)),則記錄完整文件路徑。
  • log.level: 日志級別,可選DEBUG/INFO/WARN/ERROR。

其他配置:

  • proxy.example: 代理。
  • request.concurrency: 請求并發(fā)數(shù)。
  • request.interval: 請求間隔時間(毫秒)。默認(rèn)1000毫秒(1秒)。
  • request.timeout: 請求超時時間(秒)。默認(rèn)60秒(1分鐘)。
  • request.ok_http_codes: 請求正常的HTTP狀態(tài)碼。
  • request.retry_max_times: 請求重試的最大次數(shù),默認(rèn)10。
  • request.http_proto: 請求的HTTP協(xié)議。默認(rèn)2.0
  • dev_server: 開發(fā)服務(wù)器的地址。默認(rèn)https://localhost:8081
  • enable_ja3: 是否修改/打印JA3指紋。默認(rèn)關(guān)閉。
  • scheduler: 調(diào)度方式,默認(rèn)memory(內(nèi)存調(diào)度),可選值memory、redis、kafka。選擇redis或kafka后可以實(shí)現(xiàn)集群調(diào)度。
  • filter: 過濾方式,默認(rèn)memory(內(nèi)存過濾),可選值memory、redis。選擇redis后可以實(shí)現(xiàn)集群過濾。

中間件和Pipeline配置

  • enable_stats_middleware: 是否開啟統(tǒng)計中間件,默認(rèn)啟用。
  • enable_dump_middleware: 是否開啟打印請求和響應(yīng)中間件,默認(rèn)啟用。
  • enable_filter_middleware: 是否開啟過濾中間件,默認(rèn)啟用。
  • enable_file_middleware: 是否開啟文件處理中間件,默認(rèn)啟用。
  • enable_image_middleware: 是否開啟圖片處理中間件,默認(rèn)啟用。
  • enable_http_middleware: 是否開啟HTTP請求中間件,默認(rèn)啟用。
  • enable_retry_middleware: 是否開啟請求重試中間件,默認(rèn)啟用。
  • enable_referrer_middleware: 是否開啟Referrer中間件,默認(rèn)啟用。
  • referrer_policy: 設(shè)置Referrer策略,可選值為DefaultReferrerPolicy(默認(rèn))和NoReferrerPolicy。
  • enable_http_auth_middleware: 是否開啟HTTP認(rèn)證中間件,默認(rèn)關(guān)閉。
  • enable_cookie_middleware: 是否開啟Cookie中間件,默認(rèn)啟用。
  • enable_url_middleware: 是否開啟URL長度限制中間件,默認(rèn)啟用。
  • url_length_limit: URL的最大長度限制,默認(rèn)2083。
  • enable_compress_middleware: 是否開啟響應(yīng)解壓縮中間件(gzip、deflate),默認(rèn)啟用。
  • enable_decode_middleware: 是否開啟中文解碼中間件(GBK、GB2312、Big5編碼),默認(rèn)啟用。
  • enable_redirect_middleware: 是否開啟重定向中間件,默認(rèn)啟用。
  • redirect_max_times: 重定向的最大次數(shù),默認(rèn)10。
  • enable_chrome_middleware: 是否開啟Chrome模擬中間件,默認(rèn)啟用。
  • enable_device_middleware: 是否開啟設(shè)備模擬中間件,默認(rèn)關(guān)閉。
  • enable_proxy_middleware: 是否開啟代理中間件,默認(rèn)啟用。
  • enable_robots_txt_middleware: 是否開啟robots.txt支持中間件,默認(rèn)關(guān)閉。
  • enable_dump_pipeline: 是否開啟打印Item Pipeline,默認(rèn)啟用。
  • enable_file_pipeline: 是否開啟文件下載Pipeline,默認(rèn)啟用。
  • enable_image_pipeline: 是否開啟圖片下載Pipeline,默認(rèn)啟用。
  • enable_filter_pipeline: 是否開啟過濾Pipeline,默認(rèn)啟用。
  • enable_csv_pipeline: 是否開啟csv Pipeline,默認(rèn)關(guān)閉。
  • enable_json_lines_pipeline: 是否開啟json lines Pipeline,默認(rèn)關(guān)閉。
  • enable_mongo_pipeline: 是否開啟mongo Pipeline,默認(rèn)關(guān)閉。
  • enable_mysql_pipeline: 是否開啟mysql Pipeline,默認(rèn)關(guān)閉。
  • enable_kafka_pipeline: 是否開啟kafka Pipeline,默認(rèn)關(guān)閉。
  • enable_priority_queue: 是否開啟優(yōu)先級隊(duì)列,默認(rèn)開啟,目前只支持redis。

關(guān)于結(jié)果(item)隊(duì)列

由爬蟲處理自己的請求即可,沒必要處理其他爬蟲的請求。所以本框架雖架構(gòu)上有預(yù)留,但不會去用其他外部隊(duì)列代替本程序內(nèi)存隊(duì)列。
如處理出現(xiàn)性能問題,建議將結(jié)果輸出到隊(duì)列。

關(guān)于請求隊(duì)列

  • 優(yōu)先級
    優(yōu)先級允許[0-2147483647],建議在0-255,方便后期可能的調(diào)整。
    0的優(yōu)先級最高,最先被處理。
    因?yàn)閗afka等隊(duì)列實(shí)現(xiàn)不是很好,暫不支持。
    使用方法
    request.SetPriority(0)
    

關(guān)于單次任務(wù)結(jié)束的判定

實(shí)際生產(chǎn)上,可能會有不同的判定方法,基本無法做到兼容所有情況。特別是如果要支持分布式。
一般的框架里會延時一段時間,如果隊(duì)列不再有請求,會判定任務(wù)結(jié)束,程序關(guān)閉。
本框架里單次任務(wù)的停止條件有:

  1. 請求和解析方法都已結(jié)束
  2. item隊(duì)列為空
  3. request隊(duì)列為空,同時必須有request處理過

達(dá)到以上條件程序會結(jié)束。

Example

example.go

package main

import (
    "context"
    "errors"
    "fmt"
    "github.com/lizongying/go-crawler/pkg"
    "github.com/lizongying/go-crawler/pkg/app"
    "github.com/lizongying/go-crawler/pkg/devServer"
    "github.com/lizongying/go-crawler/pkg/items"
    "github.com/lizongying/go-crawler/pkg/request"
)

type ExtraOk struct {
    Count int
}

type DataOk struct {
    Count int
}

type Spider struct {
    pkg.Spider
    logger pkg.Logger
}

func (s *Spider) ParseOk(ctx context.Context, response pkg.Response) (err error) {
    var extra ExtraOk
    err = response.UnmarshalExtra(&extra)
    if err != nil {
        s.logger.Error(err)
        return
    }

    err = s.YieldItem(ctx, items.NewItemNone().
        SetData(&DataOk{
            Count: extra.Count,
        }))
    if err != nil {
        s.logger.Error(err)
        return err
    }

    if extra.Count > 0 {
        return
    }

    err = s.YieldRequest(ctx, request.NewRequest().
        SetUrl(response.GetUrl()).
        SetExtra(&ExtraOk{
            Count: extra.Count + 1,
        }).
        SetCallBack(s.ParseOk))
    if err != nil {
        s.logger.Error(err)
    }
    return
}

func (s *Spider) TestOk(ctx context.Context, _ string) (err error) {
    // mock server
    s.AddDevServerRoutes(devServer.NewOkHandler(s.logger))

    err = s.YieldRequest(ctx, request.NewRequest().
        SetUrl(fmt.Sprintf("%s%s", s.GetHost(), devServer.UrlOk)).
        SetExtra(&ExtraOk{}).
        SetCallBack(s.ParseOk))
    if err != nil {
        s.logger.Error(err)
    }
    return
}

func NewSpider(baseSpider pkg.Spider) (spider pkg.Spider, err error) {
    if baseSpider == nil {
        err = errors.New("nil baseSpider")
        return
    }

    spider = &Spider{
        Spider: baseSpider,
        logger: baseSpider.GetLogger(),
    }
    spider.SetName("test-ok")
    host, _ := spider.GetConfig().GetDevServer()
    spider.SetHost(host.String())

    return
}

func main() {
    app.NewApp(NewSpider).Run()
}

go run exampleSpider.go -c example.yml -f TestOk -m dev

更多示例可以按照以下項(xiàng)目

go-crawler-example

git clone github.com/lizongying/go-crawler-example
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容