關於本文:
- 本文主要目的爲提綱挈領,爬蟲知識總覽
- 內容包含爬蟲所依賴的知識以及爬蟲流程
- 相關技能點請自行查找,網上文檔較全面
- 代碼演示只給了一個項目,建議動手實踐
目錄
分析工具:
- F12開發者工具-分析頁面結構/請求數據
- fillber抓包工具-分析請求數據
所需技能點-瞭解即可,建議實踐中深入研究
- 前端相關知識 html、css、js、ajax,能夠分析頁面
- http請求知識 GET/POST,請求行/頭/體,響應行/頭/體
- 請求頁面的庫 urllib&requests庫 手動編寫爬蟲使用的庫
- 解析頁面模塊 re&BS&Xpath 解析網頁數據所依賴的模塊
- 正則表達式 最原始萬能解析頁面/文本方法
- 請求頁面方式 深度/廣度 遍歷頁面的方式
- 開源爬蟲框架 scrapy ,結構清晰
- 基礎反爬策略 User Agent、代理池,快代理等免費代理
- 高級反爬策略 Pillow+pytesseract 驗證碼識別
- 模擬人工訪問 selenium 模擬人工訪問站點
- 爬蟲限制條件 robots協議 官方的爬蟲限制條件
- 官方網站地圖 sitemap,官網提供可以供訪問的url
補充:re正則中貪婪/非貪婪的區別---後者有'?'
- 貪婪:在匹配成功的前提下,儘可能多的匹配*
- 非貪婪:在匹配成功的前提下,儘可能少的匹配*
手動爬蟲流程-編碼邏輯
1. 設置種子/起始站點,運用廣度/深度算法
2. 用一個隊列保存url
3. 獲取當前頁面每個url下的外鏈
4. 遞歸調用遍歷網站獲取所有url
5. 進入每個url獲取數據
scrapy爬蟲流程-啓動過程
1. 框架安裝|命令
pip/conda install scrapy
2. 項目新建|命令
scrapy startproject [工程名]
會創建結構化的項目代碼
3. 爬蟲創建|命令
scrapy genspider [蜘蛛名稱] [網站域名]
會生成'蜘蛛名稱.py':
路徑:工程文件/spiders/蜘蛛名稱.py
4. 爬蟲配置|設置
修改settings.py中USER_AGENT等
修改middlewares.py,設置中間件,cookies、重連、重定向、ajax、代理等
修改items.py,設置ORM 關係映射,添加items數據,數據清理
修改pipelines.py:保存數據的邏輯=》數據庫|本地文件(json/excel)
5. 爬蟲編碼|主體邏輯
def parse(self,response):
添加方法即可
6. 項目啓動|命令
scrapy crawl 爬蟲名稱
數據存儲/持久化
- 結構化數據:有關聯關係的數據==》mysql存儲
- 半結構化數據:HTML,XML和JSON==》nosql存儲
非結構化數據:文檔、圖片、影音==》二進制存儲
注意:json格式嚴謹,雙引號,逗號
反爬對抗策略:
- 第一步:重構User-Agent,模擬真實瀏覽器
- 第二步:使用代理服務器,僞裝IP
- 高級:延遲、重定向、驗證碼等問題,具體情況具體解決
可練手項目:注意編解碼問題
項目 | 所需技術 | 說明 |
---|---|---|
xx貼吧圖片 | requests+lxml.etree | 結構化比較強 |
w3c教程筆記 | urllib+re | 爬取文本數據 |
ftp下載文件 | urllib+re | 需有ftp服務器 |
代碼/項目演示:爬取XX貼吧圖片
import requests
from lxml import etree
class BaiduImageSpider:
def __init__(self):
self.headers = {"User-Agent": "Mozilla5.0/"}
self.baseurl = "http://tieba.baidu.com"
self.pageurl = "http://tieba.baidu.com/f?"
# 獲取每個帖子的url
def getPageUrl(self, params):
# 得到貼吧第1頁html源碼
res = requests.get(self.pageurl, params=params, headers=self.headers)
res.encoding = "utf-8"
html = res.text
# 從html源碼獲取帖子鏈接 '/p/2323432'
parseHtml = etree.HTML(html)
t_list = parseHtml.xpath(
'//div[@class="t_con cleafix"]/div/div/div/a/@href')
# ['/p/2342443','/p/08098034']
for t in t_list:
t_url = self.baseurl + t
self.getImageUrl(t_url)
# 獲取帖子中所有圖片的URL
def getImageUrl(self, t_url):
# 獲取帖子的html源碼,爲了從中篩選圖片URL
res = requests.get(t_url, headers=self.headers)
res.encoding = "utf-8"
html = res.text
# 得到圖片URL
parseHtml = etree.HTML(html)
i_list = parseHtml.xpath('//img[@class="BDE_Image"]/@src')
#['http://...jpg','http://...png',...]
for i in i_list:
self.writeImage(i)
# 保存到本地
def writeImage(self, i):
# 獲取圖片的html源碼 bytes
res = requests.get(i, headers=self.headers)
res.encoding = "utf-8"
html = res.content
# 保存到本地
filename = i[-10:]
with open(filename, "wb") as f:
print("%s正在下載" % filename)
f.write(html)
print("%s下載成功" % filename)
# 主函數
def workOn(self):
name = input("請輸入貼吧名字:")
begin = int(input("請輸入起始頁:"))
end = int(input("請輸入終止頁:"))
for page in range(begin, end + 1):
pn = (page - 1) * 50
params = {
"kw": name,
"pn": str(pn)
}
self.getPageUrl(params)
if __name__ == "__main__":
spider = BaiduImageSpider()
spider.workOn()