詳解4種類型的爬蟲技術(shù)
導(dǎo)讀:網(wǎng)絡(luò)爬蟲是一種很好的自動采集數(shù)據(jù)的通用手段。本文將會對爬蟲的類型進行介紹。

-
聚焦網(wǎng)絡(luò)爬蟲是“面向特定主題需求”的一種爬蟲程序,而通用網(wǎng)絡(luò)爬蟲則是捜索引擎抓取系統(tǒng)(Baidu、Google、Yahoo等)的重要組成部分,主要目的是將互聯(lián)網(wǎng)上的網(wǎng)頁下載到本地,形成一個互聯(lián)網(wǎng)內(nèi)容的鏡像備份。 -
增量抓取意即針對某個站點的數(shù)據(jù)進行抓取,當(dāng)網(wǎng)站的新增數(shù)據(jù)或者該站點的數(shù)據(jù)發(fā)生變化后,自動地抓取它新增的或者變化后的數(shù)據(jù)。 -
Web頁面按存在方式可以分為表層網(wǎng)頁(surface Web)和深層網(wǎng)頁(deep Web,也稱invisible Web pages或hidden Web)。
-
表層網(wǎng)頁是指傳統(tǒng)搜索引擎可以索引的頁面,即以超鏈接可以到達的靜態(tài)網(wǎng)頁為主來構(gòu)成的Web頁面。 -
深層網(wǎng)頁是那些大部分內(nèi)容不能通過靜態(tài)鏈接獲取的、隱藏在搜索表單后的,只有用戶提交一些關(guān)鍵詞才能獲得的Web頁面。
-
【例1】一個簡單的爬取圖片的聚焦爬蟲
import urllib.request
# 爬蟲專用的包urllib,不同版本的Python需要下載不同的爬蟲專用包
import re
# 正則用來規(guī)律爬取
keyname=""
# 想要爬取的內(nèi)容
key=urllib.request.quote(keyname)
# 需要將你輸入的keyname解碼,從而讓計算機讀懂
for i in range(0,5): # (0,5)數(shù)字可以自己設(shè)置,是淘寶某產(chǎn)品的頁數(shù)
url="https://s.taobao.com/search?q="+key+"&imgfile=&js=1&stats_click=search_radio_all%3A1&initiative_id=staobaoz_20180815&ie=utf8&bcoffset=0&ntoffset=6&p4ppushleft=1%2C48&s="+str(i*44)
# url后面加上你想爬取的網(wǎng)站名,然后你需要多開幾個類似的網(wǎng)站以找到其規(guī)則
# data是你爬取到的網(wǎng)站所有的內(nèi)容要解碼要讀取內(nèi)容
pat='"pic_url":"http://(.*?)"'
# pat使用正則表達式從網(wǎng)頁爬取圖片
# 將你爬取到的內(nèi)容放在一個列表里面
print(picturelist)
# 可以不打印,也可以打印下來看看
for j in range(0,len(picturelist)):
picture=picturelist[j]
pictureurl="http://"+picture
# 將列表里的內(nèi)容遍歷出來,并加上http://轉(zhuǎn)到高清圖片
file="E:/pycharm/vscode文件/圖片/"+str(i)+str(j)+".jpg"
# 再把圖片逐張編號,不然重復(fù)的名字將會被覆蓋掉
urllib.request.urlretrieve(pictureurl,filename=file)
# 最后保存到文件夾
-
第一,獲取初始URL。初始URL地址可以由用戶人為指定,也可以由用戶指定的某個或某幾個初始爬取網(wǎng)頁決定。 -
第二,根據(jù)初始的URL爬取頁面并獲得新的URL。獲得初始的URL地址之后,需要先爬取對應(yīng)URL地址中的網(wǎng)頁,接著將網(wǎng)頁存儲到原始數(shù)據(jù)庫中,并且在爬取網(wǎng)頁的同時,發(fā)現(xiàn)新的URL地址,并且將已爬取的URL地址存放到一個URL列表中,用于去重及判斷爬取的進程。 -
第三,將新的URL放到URL隊列中,在于第二步內(nèi)獲取下一個新的URL地址之后,會將新的URL地址放到URL隊列中。 -
第四,從URL隊列中讀取新的URL,并依據(jù)新的URL爬取網(wǎng)頁,同時從新的網(wǎng)頁中獲取新的URL并重復(fù)上述的爬取過程。 -
第五,滿足爬蟲系統(tǒng)設(shè)置的停止條件時,停止爬取。在編寫爬蟲的時候,一般會設(shè)置相應(yīng)的停止條件。如果沒有設(shè)置停止條件,爬蟲便會一直爬取下去,一直到無法獲取新的URL地址為止,若設(shè)置了停止條件,爬蟲則會在停止條件滿足時停止爬取。詳情請參見圖2-5中的右下子圖。
-
【例2】爬取京東商品信息
'''
爬取京東商品信息:
請求url:https://www.jd.com/
提取商品信息:
1.商品詳情頁
2.商品名稱
3.商品價格
4.評價人數(shù)
5.商品商家
'''
from selenium import webdriver # 引入selenium中的webdriver
from selenium.webdriver.common.keys import Keys
import time
def get_good(driver):
try:
# 通過JS控制滾輪滑動獲取所有商品信息
js_code = '''
window.scrollTo(0,5000);
'''
driver.execute_script(js_code) # 執(zhí)行js代碼
# 等待數(shù)據(jù)加載
time.sleep(2)
# 查找所有商品div
# good_div = driver.find_element_by_id('J_goodsList')
good_list = driver.find_elements_by_class_name('gl-item')
n = 1
for good in good_list:
# 根據(jù)屬性選擇器查找
# 商品鏈接
good_url = good.find_element_by_css_selector(
'.p-img a').get_attribute('href')
# 商品名稱
good_name = good.find_element_by_css_selector(
'.p-name em').text.replace("\n", "--")
# 商品價格
good_price = good.find_element_by_class_name(
'p-price').text.replace("\n", ":")
# 評價人數(shù)
good_commit = good.find_element_by_class_name(
'p-commit').text.replace("\n", " ")
good_content = f'''
商品鏈接: {good_url}
商品名稱: {good_name}
商品價格: {good_price}
評價人數(shù): {good_commit}
\n
'''
print(good_content)
with open('jd.txt', 'a', encoding='utf-8') as f:
f.write(good_content)
next_tag = driver.find_element_by_class_name('pn-next')
next_tag.click()
time.sleep(2)
# 遞歸調(diào)用函數(shù)
get_good(driver)
time.sleep(10)
finally:
driver.close()
if __name__ == '__main__':
good_name = input('請輸入爬取商品信息:').strip()
driver = webdriver.Chrome()
driver.implicitly_wait(10)
# 往京東主頁發(fā)送請求
driver.get('https://www.jd.com/')
# 輸入商品名稱,并回車搜索
input_tag = driver.find_element_by_id('key')
input_tag.send_keys(good_name)
input_tag.send_keys(Keys.ENTER)
time.sleep(2)
get_good(driver)
-
在發(fā)送請求之前判斷這個URL是否曾爬取過; -
在解析內(nèi)容后判斷這部分內(nèi)容是否曾爬取過; -
寫入存儲介質(zhì)時判斷內(nèi)容是否已存在于介質(zhì)中。
-
第一種思路適合不斷有新頁面出現(xiàn)的網(wǎng)站,比如小說的新章節(jié)、每天的實時新聞等; -
第二種思路則適合頁面內(nèi)容會定時更新的網(wǎng)站; -
第三種思路則相當(dāng)于最后一道防線。這樣做可以最大限度地達到去重的目的。
-
第一,對爬取過程中產(chǎn)生的URL進行存儲,存儲在Redis的set中。當(dāng)下次進行數(shù)據(jù)爬取時,首先在存儲URL的set中對即將發(fā)起的請求所對應(yīng)的URL進行判斷,如果存在則不進行請求,否則才進行請求。 -
第二,對爬取到的網(wǎng)頁內(nèi)容進行唯一標(biāo)識的制定(數(shù)據(jù)指紋),然后將該唯一標(biāo)識存儲至Redis的set中。當(dāng)下次爬取到網(wǎng)頁數(shù)據(jù)的時候,在進行持久化存儲之前,可以先判斷該數(shù)據(jù)的唯一標(biāo)識在Redis的set中是否存在,從而決定是否進行持久化存儲。
-
【例3】爬取4567tv網(wǎng)站中所有的電影詳情數(shù)據(jù)
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from redis import Redis
from incrementPro.items import IncrementproItem
class MovieSpider(CrawlSpider):
name = 'movie'
# allowed_domains = ['www.xxx.com']
start_urls = ['http://www.4567tv.tv/frim/index7-11.html']
rules = (
Rule(LinkExtractor(allow=r'/frim/index7-\d+\.html'), callback='parse_item', follow=True),
)
# 創(chuàng)建Redis鏈接對象
conn = Redis(host='127.0.0.1', port=6379)
def parse_item(self, response):
li_list = response.xpath('//li[@class="p1 m1"]')
for li in li_list:
# 獲取詳情頁的url
detail_url = 'http://www.4567tv.tv' + li.xpath('./a/@href').extract_first()
# 將詳情頁的url存入Redis的set中
ex = self.conn.sadd('urls', detail_url)
if ex == 1:
print('該url沒有被爬取過,可以進行數(shù)據(jù)的爬取')
yield scrapy.Request(url=detail_url, callback=self.parst_detail)
else:
print('數(shù)據(jù)還沒有更新,暫無新數(shù)據(jù)可爬取!')
# 解析詳情頁中的電影名稱和類型,進行持久化存儲
def parst_detail(self, response):
item = IncrementproItem()
item['name'] = response.xpath('//dt[@class="name"]/text()').extract_first()
item['kind'] = response.xpath('//div[@class="ct-c"]/dl/dt[4]//text()').extract()
item['kind'] = ''.join(item['kind'])
yield it
from redis import Redis
class IncrementproPipeline(object):
conn = None
def open_spider(self,spider):
self.conn = Redis(host='127.0.0.1',port=6379)
def process_item(self, item, spider):
dic = {
'name':item['name'],
'kind':item['kind']
}
print(dic)
self.conn.push('movieData',dic)
# 如果push不進去,那么dic變成str(dic)或者改變redis版本
pip install -U redis==2.10.6
return item
-
基于領(lǐng)域知識的表單填寫(建立一個填寫表單的關(guān)鍵詞庫,在需要的時候,根據(jù)語義分析選擇對應(yīng)的關(guān)鍵詞進行填寫); -
基于網(wǎng)頁結(jié)構(gòu)分析的表單填寫(一般在領(lǐng)域知識有限的情況下使用,這種方式會根據(jù)網(wǎng)頁結(jié)構(gòu)進行分析,并自動地進行表單填寫)。

評論
圖片
表情
