成果:
代碼在github:
趕集爬蟲
整體思路:
1.爬取page_url焚鲜。
這個基本都是套路恤磷,很容易爬取,然后存在page_url這個數(shù)據(jù)庫中
2.爬取index檢索頁
從page_url拿出來打開的頁面票彪,進入到page_url红淡,把每個預(yù)覽頁面的url給剝離出來存到preview_url這個數(shù)據(jù)庫。必須加上驗證是否是有效頁面降铸。因為你不知道有多少頁在旱,所以就找一下數(shù)字比較大的頁面看看區(qū)別是什么樣的。
我在這里是用了大的頁面沒有page_box這個類推掸,而終止爬取
3.爬取詳情頁面
所有的頁面結(jié)構(gòu)是一樣的也就是說谅畅,他們做網(wǎng)站的輕松登渣,所以搞得我們爬取也輕松,就是這個道理毡泻。也就是說胜茧,無論電腦還是飾品分類都是一樣的頁面布局。
這步實現(xiàn)是從preview_url數(shù)據(jù)庫拿出來數(shù)據(jù)來爬取詳細信息然后存儲到info_details仇味。每個條目加上url呻顽,方便以后去重
4.整體思路就是以上,還有一些新手段:
- 去重就是在數(shù)據(jù)庫檢索有沒有這個數(shù)據(jù)一般我們提取數(shù)據(jù)庫的數(shù)據(jù)是[i['url'] for i in first_grade.find()],這樣就返回了一個列表丹墨,你在用 url in [a,b,c……]這個布爾值來判斷是否需要插入信息
新技能GET:
1.進程池廊遍,
import multiprocessing
def do_calculation(data):
return data * 2
def start_process():
print('Starting', multiprocessing.current_process().name)
if __name__ == '__main__':
inputs = list(range(10))
print('Inputs :', inputs)
# 這個是不用進程池,Python原生的方法
builtin_output = map(do_calculation, inputs)
print('Build-In :', [i for i in builtin_output])
# 用到進程池的方法
# 整個cpu_count()可以計算cpu內(nèi)核數(shù)带到,不用裝魯大師去查了
# 開了4個進程池
pool_size = multiprocessing.cpu_count() * 2
print('pool_size:', pool_size)
pool = multiprocessing.Pool(processes=pool_size,
initializer=start_process, )
pool_outputs = pool.map(do_calculation, inputs)
pool.close()
pool.join()
print('Pool outputs:', pool_outputs)
輸出是:
Inputs : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Build-In : [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
pool_size: 4
Starting SpawnPoolWorker-1
Starting SpawnPoolWorker-3
Starting SpawnPoolWorker-2
Starting SpawnPoolWorker-4
Pool outputs: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
自己寫個了東西昧碉,便于自己加深印象:
from multiprocessing import Pool
from time import *
def delay_1(i):
print('delay_one start{}'.format(i), ctime())
sleep(2)
print('delay_one end{}'.format(i), ctime())
def delay_2(i):
print('delay_two start{}'.format(i), ctime())
sleep(4)
print('delay_two end{}'.format(i), ctime())
if __name__ == '__main__':
print('all start', ctime())
pool = Pool()
# 電腦是雙核的,process=2揽惹,可以不用寫
# 設(shè)置process=4真的可以提升速度被饿,但是好像不推薦
pool.map(delay_1, [1, 2, 3, 4])
# 前者結(jié)束后后者開始
pool.map(delay_2, [1, 2])
pool.close()
pool.join()
print('all end', ctime())
輸出結(jié)果:
all start Wed Aug 10 22:44:55 2016
delay_one start1 Wed Aug 10 22:44:55 2016
delay_one start2 Wed Aug 10 22:44:55 2016
delay_one end1 Wed Aug 10 22:44:57 2016
delay_one start3 Wed Aug 10 22:44:57 2016
delay_one end2 Wed Aug 10 22:44:57 2016
delay_one start4 Wed Aug 10 22:44:57 2016
delay_one end3 Wed Aug 10 22:44:59 2016
delay_one end4 Wed Aug 10 22:44:59 2016
delay_two start1 Wed Aug 10 22:44:59 2016
delay_two start2 Wed Aug 10 22:44:59 2016
delay_two end2 Wed Aug 10 22:45:03 2016
delay_two end1 Wed Aug 10 22:45:03 2016
all end Wed Aug 10 22:45:03 2016
進程池是個什么東西呢?可以看到pool.map(func,literal)
的用法就是后面可迭代數(shù)據(jù)加到前面func中搪搏,本來我們一個參數(shù)放到一個函數(shù)運行結(jié)果出來需要2s的話狭握,4個是8s,但是我們開了多進程,默認雙核疯溺,所以進程池是兩個處理器處理數(shù)據(jù)论颅,也就是說一回可以處理2個,時間減半囱嫩,只需要4s恃疯。這是在需要大量迭代數(shù)據(jù)的進程中比較快捷的方法。
pool()之間不阻塞墨闲,一個完成以后開啟另一個
2.split的用處
str = """
1
2
3
4
"""
這樣的打出來是有格式的今妄,所以用str.split(),來處理一下,就返回一個列表每一行就是列表的一個元素
3.增加models
因為兩個py(一個a,一個b)中建立pymongo的話,a、b分別初始化的話會覆蓋掉對方盾鳞,所以增加了models,專用于
數(shù)據(jù)庫初始化犬性,如果在a中要用到models,就在文件a中import models腾仅,然后在a中:
直接models.first_grade.save(data)這樣使用乒裆。
4.import的一些問題,
如果用到A中的一些函數(shù),一定要一個一個寫出來推励,不要from A import *
,這樣沒人知道你突然用到某個 函數(shù)是從A中import的鹤耍。
文件test1.py中有兩個函數(shù):a和b,其中b用到了a函數(shù)吹艇。在test2中import了test1以后惰蜜,怎么用a函數(shù)呢?
test1.a()使用受神,用b也是用test1.b(),但是b用到了a芭撞?沒關(guān)系?真的沒關(guān)系!即便在test2中寫from test1 import b
鼻听,直接用b(),函數(shù)b()也會引用到a(),而不用我們操心去多添加一行from test2 import a
(這行是完全沒有必要的)
5.soup.find()的使用
soup.find('a', 'apple')挑選出來的就是<a class='apple'></a>元素财著,但只是符合的第一個元素,不是列表撑碴,如果
是soup.find_all()才選出所有符合的列表
總結(jié)撑教,能夠爬取10w級別數(shù)據(jù)是因為這些數(shù)據(jù)的info頁面結(jié)構(gòu)是一樣的。因為對于公司方便醉拓,所以對我們也方便伟姐。
爬蟲告一段落了,爬蟲真的沒什么難學的亿卤,基本都是套路愤兵,習慣了就好了