日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

ip代理池的爬虫编写、验证和维护

發(fā)布時(shí)間:2023/12/13 综合教程 29 生活家
生活随笔 收集整理的這篇文章主要介紹了 ip代理池的爬虫编写、验证和维护 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

打算法比賽有點(diǎn)累,比賽之余寫點(diǎn)小項(xiàng)目來提升一下工程能力、順便陶冶一下情操
本來是想買一個服務(wù)器寫個博客或者是弄個什么翻墻的東西
最后刷知乎看到有一個很有意思的項(xiàng)目,就是維護(hù)一個「高可用低延遲的高匿IP代理池」
于是就想自己把這個項(xiàng)目寫一次,其中有些更改,有些沒有實(shí)現(xiàn)
(數(shù)據(jù)結(jié)構(gòu)作業(yè)要寫廣義表,寫項(xiàng)目時(shí)發(fā)現(xiàn)還沒寫 :)

原知乎鏈接:https://www.zhihu.com/question/47464143 (作者:resolvewang)
原項(xiàng)目github鏈接:https://github.com/SpiderClub/haipproxy
在此感謝原作者 resolvewang

本項(xiàng)目鏈接:https://github.com/TangliziGit/proxypool

項(xiàng)目早已在服務(wù)器上運(yùn)行,這篇隨筆就是未完待續(xù)吧
咕咕咕,鴿了

大體思路

用爬蟲爬下網(wǎng)絡(luò)上的免費(fèi)代理ip
對爬取的代理ip進(jìn)行驗(yàn)證,過濾掉一些不可用、低速的、有網(wǎng)頁跳轉(zhuǎn)的代理
編寫調(diào)度器,對各個網(wǎng)站定時(shí)爬取、驗(yàn)證免費(fèi)代理;并對數(shù)據(jù)庫中以爬取的代理進(jìn)行驗(yàn)證
寫一個web api,提供數(shù)據(jù)庫中已有的代理ip

大體框架


(我就只是想畫個圖而已 -_-)

項(xiàng)目第一階段目錄:

proxypool/
├── booter.py
├── dump.rdb
├── place.txt
├── proxypool
│   ├── __init__.py
│   ├── items.py
│   ├── logger.py
│   ├── middlewares.py
│   ├── pipelines.py
│   ├── rules.py
│   ├── settings.py
│   ├── spiders
│   │   ├── base_spider.py
│   │   ├── common_spider.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   ├── task_queue.py
│   ├── user_agent.py
│   └── validators
│       ├── baidu_validator.py
│       ├── base_validator.py
│       ├── __init__.py
│       ├── __pycache__
│       └── zhihu_validator.py
├── __pycache__
├── scheduler.py
├── scrapy.cfg
└── testip.py

7 directories, 24 files

// wc -l `find . -name "*.py"`
    5 ./booter.py
  119 ./proxypool/middlewares.py
    5 ./proxypool/spiders/common_spider.py
   67 ./proxypool/spiders/base_spider.py
    9 ./proxypool/spiders/__init__.py
    7 ./proxypool/logger.py
   91 ./proxypool/settings.py
   11 ./proxypool/user_agent.py
   86 ./proxypool/rules.py
   57 ./proxypool/task_queue.py
    7 ./proxypool/validators/zhihu_validator.py
    7 ./proxypool/validators/baidu_validator.py
   56 ./proxypool/validators/base_validator.py
    5 ./proxypool/validators/__init__.py
   55 ./proxypool/pipelines.py
   21 ./proxypool/items.py
    0 ./proxypool/__init__.py
   59 ./scheduler.py
  667 total

細(xì)節(jié)描述

爬蟲部分

數(shù)據(jù)流向
RedisTaskQueue獲取鏈接
Spider發(fā)出請求
RandomUserAgentMiddware換UA
通過規(guī)則解析response
送至RedisRawProxyPipeline,未處理數(shù)據(jù)存入數(shù)據(jù)庫

爬取規(guī)則的編寫
很多免費(fèi)代理網(wǎng)站的結(jié)構(gòu)都很相似,基本上就是這樣的(取自西刺代理):

  <tr class="odd">
    <td class="country"><img src="http://fs.xicidaili.com/images/flag/cn.png" alt="Cn" /></td>
    <td>223.240.209.18</td>
    <td>18118</td>
    <td>安徽合肥</td>
    <td class="country">高匿</td>
    <td>HTTP</td>
      <td>1分鐘</td>
    <td>不到1分鐘</td>
  </tr>
  <tr class="">
    <td class="country"><img src="http://fs.xicidaili.com/images/flag/cn.png" alt="Cn" /></td>
    <td>183.23.73.49</td>
    <td>61234</td>
    <td>廣東東莞</td>
    <td class="country">高匿</td>
    <td>HTTPS</td>
      <td>1小時(shí)</td>
    <td>不到1分鐘</td>
  </tr>
...

通過編寫爬取規(guī)則,我們就可以很方便爬取多個網(wǎng)站:

RULES = {
    "xici" : {
        "parser_type": "page",
        "prefix": "http://tr",
        "detail": "td/text()",
        ...
    }
}

然后就可以類似這樣做請求:

[x.xpath(rule["detail"]) for x in response.xpath(rule["prefix"])]

設(shè)計(jì)RedisTaskQueue類,讓爬蟲從中取得要爬取的網(wǎng)站
為啥不讓爬蟲自己從數(shù)據(jù)庫里取任務(wù)呢?
呃 這個本來是為了多進(jìn)程做的考慮,但是發(fā)現(xiàn)scrapy的Spider已經(jīng)滿足時(shí)間上的需求了
考慮到以后可能需要這個類來讓調(diào)度器調(diào)度爬蟲,于是就留下來了

設(shè)計(jì)基本爬蟲BaseSpider
主要是以后用來做爬蟲種類的拓展,比如這個網(wǎng)頁可能會用js做個動態(tài)加載
后續(xù)就要考慮到編寫JsSpider(BaseSpider)
目前只有一個爬蟲CommonSpider(BaseSpider),用來爬普通網(wǎng)頁(普通網(wǎng)頁或json)

Scrapy框架方面
RawProxyUrlItem, ProxyUrlItem
RandomUserAgentMiddleware, TimerMiddleware
RedisRawProxyPipeline, RedisProxyPipeline

驗(yàn)證部分

數(shù)據(jù)流向
RedisProxyQueue獲取ip
Spider發(fā)出驗(yàn)證請求
TimerMiddleware開始計(jì)時(shí)
TimerMiddleware結(jié)束計(jì)時(shí)
通過規(guī)則驗(yàn)證response
驗(yàn)證通過,送至RedisRawProxyPipeline,驗(yàn)證后ip存入數(shù)據(jù)庫

驗(yàn)證規(guī)則
與爬取規(guī)則相同,我們可選許多網(wǎng)站來做驗(yàn)證(每個代理對各網(wǎng)站有不同的效率)
為了方便管理,寫驗(yàn)證規(guī)則
為什么要驗(yàn)證?
一是為了保證代理速度
二是為了保證不會存在“調(diào)包”的情況(中間人偷偷改了回復(fù))

代理記分方式
簡單的用請求時(shí)間來作為分?jǐn)?shù),存入Redis的有序集合

數(shù)據(jù)庫部分

數(shù)據(jù)項(xiàng) 描述
ProxyPool:RAW_IPPOOL 集合 存儲未驗(yàn)證ip
ProxyPool:IPPOOL 有序集合 存儲驗(yàn)證通過ip 按分?jǐn)?shù)排序
ProxyPool:TASK_QUEUE 調(diào)度器暫時(shí)存入請求鏈接

調(diào)度器部分

這部分未完待續(xù)
僅僅寫了獲取爬蟲和驗(yàn)證爬蟲的簡單啟動
下一步是根據(jù)爬取規(guī)則的時(shí)間間隔來調(diào)度

WebAPI部分

這部分根本還沒寫
不過這是項(xiàng)目里最簡單的東西
準(zhǔn)備適當(dāng)時(shí)間入一個服務(wù)器,用Flask簡單寫一寫就好了

總結(jié)要點(diǎn)

在項(xiàng)目里專門寫一個配置文件,用以配置工程內(nèi)所有信息,避免hardcode
未來可能需要更多相似的類時(shí),編寫基類是必須的,考慮到方便編寫和復(fù)用性
給類中添加某一功能時(shí),如果項(xiàng)目較復(fù)雜,寫Mixin合適一點(diǎn)
若對大量(或后續(xù)可能大量)的網(wǎng)站做爬取時(shí),最好抽象出爬取規(guī)則,便于處理添加更多爬取網(wǎng)站、更改爬取數(shù)據(jù)順序等
驗(yàn)證代理ip,考慮代理速度和中間人“調(diào)包”的可能
使用無表的數(shù)據(jù)庫(such as Redis)時(shí),為了結(jié)構(gòu)清晰,將鍵值寫成"XXX:A:B"的形式

實(shí)現(xiàn)細(xì)節(jié)&需要注意的

每一個scrapy.Spider里可以自定義設(shè)置
比如設(shè)置pipeline, middleware, DOWNLOAD_DELAY

    custom_settings = {
        'DOWNLOAD_TIMEOUT': 1,
        'CONCURRENT_REQUESTS': 50,
        'CONCURRENT_REQUESTS_PER_DOMAIN': 50,
        'RETRY_ENABLED': False,
        'DOWNLOADER_MIDDLEWARES': {
            'proxypool.middlewares.TimerMiddleware': 500,
        },
        'ITEM_PIPELINES': {
            'proxypool.pipelines.RedisProxyPipeline': 200,
        }
    }

Python取數(shù)據(jù)庫的數(shù)據(jù)后,要看看是不是byte類型
scrapy.Request包括errback, dont_filter等很有用的參數(shù)
scrapy通過CrawlerProcess方法不能重復(fù)啟動爬蟲,如有需要,用多進(jìn)程即可

**未完待續(xù)**

總結(jié)

以上是生活随笔為你收集整理的ip代理池的爬虫编写、验证和维护的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。