爬蟲之全站爬取方法

方法

做過好幾個關於網站全站的項目,這裏總結一下。

先把上面那張圖寫下來,全站爬取的兩種方法:

  1. 關係網絡:
    1. 優點:簡單;可以抓取“熱門”數據
    2. 缺點:無法抓取全量數據;速度慢;需要解決去重問題
    3. 可行性:比較高
  2. 遍歷ID
    1. 優點:可以抓取所有數據;不用數據去重
    2. 缺點:資源消耗大;速度慢;可能被發現
    3. 可行性:僅可用於ID自增

看圖

關於關係網絡

其實這個很好理解。比如說知乎,一個大V有100W粉絲,從這個大V出發,抓取粉絲的粉絲,一直循環下去。(可能是個死循環)

這個方法就比較簡單,Scrapy中就是繼承CrawlSpider,再編寫匹配規則就好。

Example

import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor

class MySpider(CrawlSpider):
    name = 'example.com'
    allowed_domains = ['example.com']
    start_urls = ['http://www.example.com']

    rules = (
        # Extract links matching 'category.php' (but not matching 'subsection.php')
        # and follow links from them (since no callback means follow=True by default).
        Rule(LinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))),

        # Extract links matching 'item.php' and parse them with the spider's method parse_item
        Rule(LinkExtractor(allow=('item\.php', )), callback='parse_item'),
    )

    def parse_item(self, response):
        self.logger.info('Hi, this is an item page! %s', response.url)
        item = scrapy.Item()
        item['id'] = response.xpath('//td[@id="item_id"]/text()').re(r'ID: (\d+)')
        item['name'] = response.xpath('//td[@id="item_name"]/text()').extract()
        item['description'] = response.xpath('//td[@id="item_description"]/text()').extract()
        return item

這種方法一般是搜索引擎會做的。而且抓取的內容基本是最多人看到的,所以月排在前面,和SEO有關。

但是這種方法的缺點也是很明顯的,最明顯的就是沒法抓全數據,像那種冷門的數據就沒法抓取到,速度也是比較慢的,必須保存去重隊列,以防止重複抓取頁面。(瞭解下布隆過濾器)

如果對數據完整性要求沒那麼高可以考慮這種方法。

遍歷ID

找各種方法就比較無腦了,啥也不用想,從0開始遍歷跑吧。

毫無疑問,這種方法可以抓取網站所有的數據,因爲在開始抓取前就已經完成的去重,所以這方面就不用管了。

但是缺點也很明顯,因爲是遍歷ID,所以需要很多服務器資源和代理資源,有可能某個ID已經下架或失效。所以整個工程請求量會非常大。而且可能被別人發現,一般人都去看那些熱門帖子,結果你把那麼重來沒人看的翻了一遍,別人也會發現數據異常的(也會存在假數據的情況?)。

而且這種方法之適用於ID自增的,大多數是數字ID遞增,比如說天眼查的:

https://www.tianyancha.com/company/24762997
https://www.tianyancha.com/company/150041670
https://www.tianyancha.com/company/1073358312

知乎的

https://zhuanlan.zhihu.com/p/47969297
https://zhuanlan.zhihu.com/p/48652497
https://zhuanlan.zhihu.com/p/47805332

應該是和數字有關係,可以先採樣進行抓取,研究數據分佈情況。

當提供不正確ID時,也會返回數據不存在的情況

在這裏提供一個生成ID的方法

def gen_uid(num):
    """
    使用生成器生成ID
    :param num: 起始ID
    :return: 生成器
    """
    js = 0
    result = list()
    while js < 20000:
        num += 1
        js += 1
        result.append(num)

    yield result

最後再看看這張圖。兩種方法都有優缺點,根據實際需求選取,如果你還知道別的抓取方法,歡迎指出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章