目的css
學習如何從互聯網上獲取數據。數據科學必須掌握的技能之一。html
本文所用到的第三方庫以下: requests, parsel, seleniummysql
requests負責向網頁發送HTTP請求並獲得響應,parsel負責解析響應字符串,selenium負責JavaScript的渲染。git
網絡爬蟲是什麼github
網絡爬蟲是一種按照必定的規則,自動地抓取網站信息的程序或者腳本。web
如何爬取網站信息ajax
寫爬蟲以前,咱們必須確保可以爬取目標網站的信息。sql
不過在此以前必須弄清如下三個問題:chrome
網站是否已經提供了api數據庫
網站是靜態的仍是動態的
網站是否有反爬的對策
情形1:開放api的網站
一個網站假若開放了api,那你就能夠直接GET到它的json數據。
好比xkcd的about頁就提供了api供你下載
import requests
requests.get('https://xkcd.com/614/info.0.json').json()
那麼如何判斷一個網站是否開放api呢?有3種方法:
在站內尋找api入口
用搜索引擎搜索「某網站 api」
抓包。有的網站雖然用到了ajax(好比果殼網的瀑布流文章),可是經過抓包仍是可以獲取XHR裏的json數據的。
怎麼抓包:F12 - Network - F5刷新便可 | 或者用fiddle等工具也能夠
情形2:不開放api的網站
若是此網站是靜態頁面,那麼你就能夠用requests庫發送請求,再用HTML解析庫(lxml、parsel等)來解析響應的text
解析庫強烈推薦parsel,不只語法和css選擇器相似,並且速度也挺快,Scrapy用的就是它。
你須要瞭解一下css選擇器的語法(xpath也行),而且學會看網頁的審查元素。
好比獲取konachan的全部原圖連接
from parsel import Selector
res = requests.get('https://konachan.com/post')
tree = Selector(text=res.text)
imgs = tree.css('a.directlink::attr(href)').extract()
若是此網站是動態頁面,先用selenium來渲染JS,再用HTML解析庫來解析driver的page_source。
好比獲取hitomi.la的數據(這裏把chrome設置成了無頭模式)
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
driver.get('https://hitomi.la/type/gamecg-all-1.html')
tree = Selector(text=driver.page_source)
gallery_content = tree.css('.gallery-content > div')
情形3:反爬的網站
目前的反爬策略常見的有:驗證碼、登陸、封ip等。
驗證碼:利用打碼平臺破解(若是硬上的話用opencv或keras訓練圖)
登陸:利用requests的post或者selenium模擬用戶進行模擬登錄
封ip:買些代理ip(免費ip通常都無論用),requests中傳入proxies參數便可
其餘防反爬方法:假裝User-Agent,禁用cookies等
推薦用fake-useragent來假裝User-Agent
from fake_useragent import UserAgent
headers = {'User-Agent': UserAgent().random}
res = requests.get(url, headers=headers)
如何編寫結構化的爬蟲
若是能成功地爬取網站信息,那麼你已經成功了一大半。
其實爬蟲的架構很簡單,無非就是創造一個tasklist,對tasklist裏的每個task調用crawl函數。
大多數網頁的url構造都是有規律的,你只需根據它用列表推倒式來構造出tasklist對於那些url不變的動態網頁,先考慮抓包,不行再用selenium點擊下一頁
若是追求速度的話,能夠考慮用concurrent.futures或者asyncio等庫。
import requests
from parsel import Selector
from concurrent import futures
domain = 'https://www.doutula.com'
def crawl(url):
res = requests.get(url)
tree = Selector(text=res.text)
imgs = tree.css('img.lazy::attr(data-original)').extract()
# save the imgs ...
if __name__ == '__main__':
tasklist = [f'{domain}/article/list/?page={i}' for i in range(1, 551)]
with futures.ThreadPoolExecutor(50) as executor:
executor.map(crawl, tasklist)
數據存儲的話,看你的需求,通常都是存到數據庫中,只要熟悉對應的驅動便可。
經常使用的數據庫驅動有:pymysql(MySQL),pymongo(MongoDB)
若是你須要框架的話
文章讀到這裏,你應該對爬蟲的基本結構有了一個清晰的認識,這時你能夠去上手框架了。
輕量級框架(looter):https://github.com/alphardex/looter
工業級框架(scrapy):https://github.com/scrapy/scrapy