最近這兩週在忙着給公司爬一點數據,更文的速度有一點下降,預計今天就爬完了,總結總結經驗。
其實之前我司是有專門做爬蟲的,不用前端這邊出人幹活。後來那人離職了,有可能就沒有爬蟲這方面的需求了。突然又有了一些,前端這邊出人做一下。老大說用 py
做,前期先調研一下。
原理
爬蟲其實原理上很簡單,我們==客戶端,他們==服務端。
客戶端發送請求 req
,服務端返回響應 rsp
。拿到響應之後解析數據,入庫,就完事了。
請求數據 req
一般來說請求分爲兩種,拉數據 get
比較多。
偶爾部分接口需要登錄,那就是多帶 cookie
或者 headers
。
其實還有一部分工作就是分析入參。
-
get
參數拼接在url
上 -
post
參數放在body
裏
響應數據 rsp
返回數據大體上是兩種
-
JSON
一般來說,通過 抓包 或者說 network 工具。我們找到了服務端的接口,那麼我直接訪問這個接口即可。
本文第一個重點來了:切換到移動端再查一遍,往往有不一樣的收穫,一般來說PC
和M
端的進度不了,有可能都不是一個項目組,所以實現方式就會有差別。 -
html
比較坑的一種方式,因爲沒有找到JSON
接口。無奈只能走解析HTML
的路子。
調研
-
Node
之前給後臺搭架子的時候使用過,主要功能點如下:- 自動登錄,(拿
headers、cookie
) - 存儲本地,每次請求帶上
token
- 啓動代理服務
- 自動登錄,(拿
-
py
老大說要用這個東西。諮詢了一下其他朋友,說可以使用下面的工具。-
requests
+beautifulSoup
使用起來其實就是requests
發請求,beautifulSoup
解析HTML
。比較原始。 -
scrapy
一個爬蟲的框架。我在這裏學的 www.scrapyd.cn。實現上比較完整,可以設置請求間隔,隨機ua
等功能。
-
-
前端實現
我一個鐵頭娃,怎麼能輕言放棄?身爲一個前端er,還是這些api
讓我更加親切-
XHR
發請求利器,打開對方頁面,cookie
啥的都自帶。無敵就是這麼寂寞。
其實還可以找到對方請求發起的位置,打個斷點,把對方內部的代碼綁定到全局,這樣一些內部邏輯什麼的也都沒問題。
而且還 JSON HTML 通吃。 -
iframe
針對HTML
類型的處理。同域的情況下,也無敵好嗎?-
HTML
獲取DOM
節點? - 甚至可以取
window
上的對象。vue SSR 你感覺到了威脅嗎?
-
-
-
網上其他服務商提供的接口(真香啊)。有免費的有收費的,一般免費的限量。
- 比如抖音熱度?
- 比如各類音樂的歌單和作品?
- IP 查詢
- 天氣查詢
好了上面說了那麼多,建議老大限制,我選擇了 scrapy
。
scrapy
scrapy
是一個網頁爬蟲框架,神馬叫做爬蟲,如果沒聽說過,那就:內事不知問度娘,外事不決問谷歌,百度或谷歌一下吧!……(這裏的省略號代表scrapy
很牛逼,基本神馬都能爬,包括你喜歡的蒼老師……這裏就不翻譯了)
看到這個騷的飛起的介紹了嗎?沒錯,我就是在上面學的。scrapy 中文站。接下來我就介紹一下我認爲對於新手比較關注的東西
scrapy HTML
scrapy
處理器中的 response
標識你拿到的 rsp 上面自帶了一些方法,一般來說需要關注的只有兩個
css 選擇器
quote.css('span.text::text').extract_first()
中的 'span.text::text'
眼熟嗎?
沒錯,就是我們常用的選擇器。通過這個 api
,我們可以把我們想要的數據,限時在一個很小的範圍,然後拿字符串即可。
啥?你說你不會 css
選擇器?前端培訓-初級階段(5 - 8)-CSS選擇器(基本、層級、屬性、僞類、僞狀態)
-
extract()
函數提取列表 -
extract_first()
代表提取第一個元素。基本等價於extract()[0]
-
::text
選擇其中的文字 -
::attr(href)
提取屬性
xpath
quote.xpath('span/small/text()').extract_first()
文檔,這個我不會,我也沒看
scrapy JSON
import json
使用這個類庫解析如:json.loads(response.body.decode('utf-8'))
scrapy 請求方式
get
import urllib
可以用來給中文字符 encode
yield scrapy.FormRequest(
url,
method = 'GET',
headers = self.headers,
formdata={},
callback = self.parse_list,
dont_filter = True,
meta = {
'offset': 0,
})
post
數據放入 formdata
傳遞即可。
yield scrapy.FormRequest(
url,
method = 'GET',
headers = self.headers,
formdata={},
callback = self.parse_list,
dont_filter = True,
meta = {
'offset': 0,
})
外部傳參方式
scrapy crawl argsSpider -a tag=愛情
內部是使用如下命令可以接收到。
def start_requests(self):
url = 'http://lab.scrapyd.cn/'
tag = getattr(self, 'tag', None) # 獲取tag值,也就是爬取時傳過來的參數
scrapy mysql
大數據那邊說爬回來的數據要入庫。
-
scrapyMysql/scrapyMysql/items.py
編寫對應入庫字段。import scrapy class ScrapymysqlItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() tag = scrapy.Field() # 標籤字段 cont = scrapy.Field() # 名言內容 pass
-
scrapyMysql/scrapyMysql/spiders/inputMysql.py
寫爬蟲處理操作時,入庫item = ScrapymysqlItem() # 實例化item類 for v in mingyan: # 循環獲取每一條名言裏面的:名言內容、作者、標籤 item['cont'] = v.css('.text::text').extract_first() # 提取名言 tags = v.css('.tags .tag::text').extract() # 提取標籤 item['tag'] = ','.join(tags) # 數組轉換爲字符串 yield item # 把取到的數據提交給pipline處理
-
編寫MySQL存儲插件:
MySQLPipeline.py
import pymysql.cursors class MySQLPipeline(object): def __init__(self): # 連接數據庫 self.connect = pymysql.connect( host='127.0.0.1', # 數據庫地址 port=3306, # 數據庫端口 db='scrapyMysql', # 數據庫名 user='root', # 數據庫用戶名 passwd='root', # 數據庫密碼 charset='utf8', # 編碼方式 use_unicode=True) # 通過cursor執行增刪查改 self.cursor = self.connect.cursor() def process_item(self, item, spider): self.cursor.execute( """insert into mingyan(tag, cont) value (%s, %s)""", # 純屬python操作mysql知識,不熟悉請惡補 (item['tag'], # item裏面定義的字段和表字段對應 item['cont'],)) # 提交sql語句 self.connect.commit() return item # 必須實現返回
-
settings啓動MySQLPipline組件
ITEM_PIPELINES = { 'scrapyMysql.MySQLPipline.MySQLPipeline': 300, }
總結一下
到現在,我們已經完成了所有基礎知識的積累。遇到不會我們去裏看?。
總結一下需要注意點的
- 切換 PC 和 M 端,尋找可行的方案
- 注意節制(部分容易限量)
- python 編碼問題(真的好煩)
- 網上提供的那個
mysql
庫和我的不合,我換了一個MySQLdb
- 第三方的接口是真香
微信公衆號