主要模塊

#1 簡易爬蟲.jpg
主要由這幾部分組成:
- 爬蟲調(diào)度端(spider_main): 對爬蟲流程進(jìn)行控制
- url管理器(url_manager): 對要爬取的url進(jìn)行管理
- 網(wǎng)頁下載器(download_manager): 對希望爬取的網(wǎng)頁進(jìn)行下載
- 網(wǎng)頁解析器(html_parser): 對下載好的網(wǎng)頁進(jìn)行解析,如果需要對網(wǎng)頁中的其它鏈接進(jìn)行下載,則將解析好的url添加到url管理器中
- 循環(huán)上面步驟,然后將有價(jià)值的信息存儲下來
整個(gè)流程

#2 流程圖.jpg
看上面的流程圖:
- 調(diào)度器詢問URL管理器,是否有待爬的url?
- 如果得到肯定回復(fù),則將獲取的url添加到URL管理器中
- URL管理器將待爬的數(shù)據(jù)返給調(diào)度器,調(diào)度器調(diào)用下載器進(jìn)行URL內(nèi)容下載
- 然后調(diào)度器將下載好的內(nèi)容交給解析器進(jìn)行解析, 收集有用數(shù)據(jù)
URL調(diào)度器

#3 URL管理器.jpg
URL管理器的主要原理就是:將已經(jīng)爬取的或待爬取的分成2類,避免重復(fù)循環(huán)爬取

#4 URL管理器實(shí)現(xiàn)方式.jpg
其實(shí)現(xiàn)方式有3種:
- 小的應(yīng)用使用內(nèi)存,使用
set數(shù)據(jù)結(jié)構(gòu)存儲 - 也可以使用數(shù)據(jù)庫對urls進(jìn)行存儲查詢
- 使用redis,一般用于比較大的爬蟲操作
網(wǎng)頁下載器

#5 網(wǎng)頁下載器.jpg
網(wǎng)頁下載器可以使用python內(nèi)置的 urllib.request 中的 urlopen 方法
另外下載網(wǎng)頁時(shí)可能遇到的問題:
- 需要模擬頭信息
- 需要登錄之后才能查看網(wǎng)頁的情況
- 權(quán)限限制
- 網(wǎng)頁是異步加載的,所以直接去下載得不到內(nèi)容
from urllib.request import urlopen
from urllib import request
import http.cookiejar
url = 'http://www.imooc.com/video/10683'
print('第1種方法')
response1 = urlopen(url)
print(response1.getcode()) # 獲取狀態(tài)碼
print(len(response1.read()))
print('第2種方法, 添加請求頭信息')
req = request.Request(url)
req.add_header('user-agent', 'Mozilla/5.0') # 添加頭信息
response2 = urlopen(req)
print(response2.getcode())
print(len(response2.read()))
print('第3種方法, 添加cookie')
cj = http.cookiejar.CookieJar()
opener = request.build_opener(request.HTTPCookieProcessor(cj))
request.install_opener(opener)
response3 = urlopen(url)
print(response3.getcode())
print(cj)
print(response3.read())
網(wǎng)頁解析器
對網(wǎng)頁進(jìn)行解析,有4種方式:
- 使用正則表達(dá)式進(jìn)行模糊匹配,用的很少
- 使用內(nèi)置的
html.parser - 使用內(nèi)置的
Ixml - 使用第3方的插件,比如
BeautifulSoup, 這個(gè)插件實(shí)現(xiàn)了上面的多種方式
BeautifulSoup的基本操作
from bs4 import BeautifulSoup
import re
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a class="sister" id="link1"><small>Elsie</small></a>,
<a class="sister" id="link2">Lacie</a> and
<a class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
# 定義一個(gè)soup, 3個(gè)參數(shù)分別為
# 解析的字符串
# 使用的解析器, 還可以使用'Ixml'
# 使用的編碼格式
soup = BeautifulSoup(html_doc, 'html.parser', from_encoding='utf-8')
print('----獲取所有的a標(biāo)簽----')
links_nodes = soup.find_all('a')
for link in links_nodes:
print(link.name, link['href'], link.get_text()) # name表示標(biāo)簽名 get_text()表示內(nèi)部文字
print('----獲取lacie的a標(biāo)簽----')
link_node = soup.find('a', )
print(link_node.name, link_node['href'], link_node.get_text())
print('----使用正則獲取a標(biāo)簽href中包含"ill"的----')
link_spec = soup.find('a', href=re.compile(r'ill'))
print(link_spec.name, link_spec['href'], link_spec.get_text())
print('----獲取class為title的p元素----')
p_nodes = soup.find_all('p', class_='title') # 因?yàn)閏lass是關(guān)鍵詞,所以這里使用'class_'
# 還可以使用dict的形式
# p_nodes = soup.find_all('p', {'class': 'title'})
for p in p_nodes:
print(p.name, p.get_text())
抓取策略
這個(gè)其實(shí)是整個(gè)業(yè)務(wù)的核心
- 你要明白你要抓取的內(nèi)容是什么
- 入口頁面是什么
- 抓取數(shù)據(jù)的規(guī)律
- 對抓取數(shù)據(jù)希望是如何進(jìn)行處理

#6 抓取策略.jpg
github地址
本文章來自慕課網(wǎng)Python開發(fā)簡單爬蟲的學(xué)習(xí)筆記, 原教程采用的python版本是2.7,我自己實(shí)現(xiàn)的是使用v3.6版本,2者之間差異不大
github 地址: