爬蟲學習筆記
爬蟲的概念
模擬瀏覽器發起請求,獲取響應數據
爬蟲的流程
url--->響應內容--->抓取數據--->保存到數據庫
爬蟲要根據當前URL地址對應的響應爲準,當前URL地址的elements的內容和URL的響應不一樣
當前URL地址對應的響應中
其他URL地址對應的響應中
比如ajax請求中
js生成的
部分數據在響應中
全部通過js生成
URL組成部分
形式 scheme://host[:port#]/path/…/[?query-string][#anchor]
scheme:協議(例如:http, https, ftp)
host:服務器的IP地址或者域名
port:服務器的端口(如果是走協議默認端口,80 or 443)
path:訪問資源的路徑
query-string:參數,發送給http服務器的數據
anchor:錨(跳轉到網頁的指定錨點位置)
http://localhost:4000/file/part01/1.2.html
http://item.jd.com/11936238.html#product-detail
requests中的解決編解碼的方法
response.content.decode()
response.content.decode('gbk')
response.text
使用代理IP
-準備一堆的ip地址,隨機選擇一個ip使用
-如何隨機選擇代理ip,讓使用次數比較少的有更大可能被用到
-{‘ip’:ip,'times':0}
-[{},{},{}]對這個ip列表進行遍歷
Requests相關
http://docs.python-requests.org/zh_CN/latest/user/quickstart.html
正則使用的注意點
-re.findall("a(.*?)","str),能夠返回括號中的內容,括號前後的內容祈禱定位和過濾的效果
-原始字符串r,待匹配字符串中有反斜槓\的時候,會讓轉義效果失效
-點號.默認匹配不到換行符\n
-\s能匹配到空白字符,不僅僅包含空格,還有\t|\r\n
Python compile() 函數
將一個正則表達式編譯成python可識別的模式,這個模式的方法有findall(),sub()
描述
compile() 函數將一個字符串編譯爲字節代碼。
語法
以下是 compile() 方法的語法:
compile(source, filename, mode[, flags[, dont_inherit]])
參數
- source – 字符串或者AST(Abstract Syntax Trees)對象。。
- filename – 代碼文件名稱,如果不是從文件讀取代碼則傳遞一些可辨認的值。
- mode – 指定編譯代碼的種類。可以指定爲 exec, eval, single。
- flags – 變量作用域,局部命名空間,如果被提供,可以是任何映射對象。。
- 1).re.I(re.IGNORECASE): 忽略大小寫
- 2).re.M(MULTILINE): 多行模式,改變’^’和’$’的行爲
- 3).re.S(DOTALL): 點任意匹配模式,改變’.’的行爲
- 4).re.L(LOCALE): 使預定字符類 \w \W \b \B \s \S 取決於當前區域設定
- 5).re.U(UNICODE): 使預定字符類 \w \W \b \B \s \S \d \D 取決於unicode定義的字符屬性
- 6).re.X(VERBOSE): 詳細模式。這個模式下正則表達式可以是多行,忽略空白字符,並可以加入註釋
- flags和dont_inherit是用來控制編譯源碼時的標誌
返回值
返回表達式執行結果。
xpath學習重點
正則如何進行非貪婪匹配,在div標籤中的數據如何通過正則取出來
- *? +?
- re.findall(“.?(.?)“,str) 返回列表,沒有匹配到就是空列表
xpath如何獲取文本,如何獲取任意標籤下的文本 - a/text() 只能獲取a下的文本
- a//text() 能夠獲取a下的和a包含的標籤的文本
- a[text()=”下一頁”]
xpath如何獲取屬性,如何對標籤進行定位 - a/@href
- div[@class=’b’]
xpath中//有什麼用 - //自最前面的時候,表示html中任意位置開始選擇
- div//* 放在節點後面的時候,能夠選擇當前節點下的所有的標籤
xpath獲取某一個或者某幾個 - //a[1] 第一個
- //a[last()] 最後一個
- //a[position()<=3]
- //a[1]|//a[3]
xpath的包含
//div[contains(@class,’i’)] # class屬性裏包含“i”的內容
lxml如何如何使用,如何把lxml處理之後的內容轉化爲字符串
- from lxml import etree
- element = etree.HTML(bytes、str) #把字符串轉化爲element對象
- etree.tostring(element) #把element對象轉化爲字符串
- element.xpath(“xpath_str”)
實現爬蟲的套路
- 準備url
- 準備start_url
- url地址規律不明顯,總數不確定
- 通過代碼提取下一頁的url
- xpath
- 尋找url地址,部分參數在當前的響應中(比如,當前頁碼數和總頁碼數在當前響應中)
- 準備url_list
- 頁碼總數明確
- url地址規律明顯
- 發送請求,獲取響應
- 添加隨機的User-Agent,反反爬蟲
- 添加隨機的代理ip
- 在對方判斷出我們是爬蟲後,應該添加更多的headers字段包括cookie
- cookie的處理可以使用session解決
- 準備一堆的cookie,組成cookie池
- 如果不登錄
- 準備剛開始能夠成功請求對方網站的cookie,即接收對方設置在response的cookie
- 下一次請求的時候,使用之前的列表中的cookie來請求
- 如果登陸
- 準備多個帳號
- 使用程序獲取多個帳號的cookie
- 之後請求登陸之後才能訪問的網站隨機的選擇cookie
- 提取數據
- 確定數據的位置
- 如果數據在當前的url地址中
- 提取的是列表頁的數據
- 直接請求列表頁的url地址,不用進入詳情頁
- 提取的是詳情頁數據
- 1、確定url
- 2、發送請求
- 3、提取數據
- 4、返回保存
- 如果數據不在當前的url地址中
- 在其他的響應中,尋找數據的位置
- 1、從network中從上到下找
- 2、使用Chrome中的過濾條件,選擇除了js,css,哦買噶,之外的按鈕
- 3、使用Chrome的search all file,搜索數字和英文
- 數據的提取
- xpath,從html中提取整塊的數據,先分組,之後每一組再提取
- re,提取max_time,price,html中的json字符串
- json
- 數據保存
- 保存在本地,text,json,csv
- 保存在數據庫
“如今你的氣質裏,藏着你走過的路,讀過的書和愛過的人。” ——《卡薩布蘭卡》
selenium和phantomJS
# 用戶名
username = 'dotcoo'
# 密碼
password = 'dotcoo'
# 軟件ID,開發者分成必要參數。登錄開發者後臺【我的軟件】獲得!
appid = 4916
# 軟件密鑰,開發者分成必要參數。登錄開發者後臺【我的軟件】獲得!
appkey = '7b392d65faf3ca3167be1ae94448e3e5'
MongoDB
mongodb插入數據
- db.collection.insert({}),_id存在會報錯
- db.collection.save({}),_id存在會更新
mongodb的更新操作
- db.collection.update({name:”ming”},{name:”hong”}),把ming更換爲hong
- db.collection.update({name:”hong”},{$set:{name:”ling”}}), 指定把hong替換爲ling
- {multi:true}更換多條
刪除
- db.collection.remove({name:”hong”},{justOne:true})
- 默認會刪除多條滿足的數據,{justOne:true}只刪除一條
count方法
- db.collection.find().count()
- db.collection.count({})
投影
- 選擇返回結果的字段
- db.collection.find({條件},{name:1,_id:0})
- 1、_id默認會顯示。置爲0不顯示
- 2、除了_id之外的其它字段,需要顯示則寫1,不顯示不寫,不能寫0
group的注意點
- $group 對應的字典中有幾個鍵,結果中就有幾個鍵
- 分組依據需要放到_id 後面
- 取不同字段的值需要使用,例如”gender,$age”
- 取字典嵌套的字典中的值時$_id.country
- 能夠同時按照多個健將進行分組 { country",province:"$province”}}}
- 結果是:{_id:{country:”“,province:”“}}
mongodb mysql redis的區別和使用場景
- mysql是關係型數據庫,支持事物
- mongodb,redis非關係型數據庫,不支持事物
- mysql,mongodb,redis的使用根據如何方便進行選擇
- 希望速度快的時候,選擇mongodb或者是redis
- 數據量過大的時候,選擇頻繁使用的數據存入redis,其他的存入mongodb
- mongodb不用提前建表建數據庫,使用方便,字段數量不確定的時候使用mongodb
- 後續需要用到數據之間的關係,此時考慮mysql
爬蟲數據去重,實現增量式爬蟲
- 使用數據庫建立關鍵字段(一個或者多個)建立索引進行去重
- 根據url地址進行去重
- 使用場景:
- url地址對應的數據不會變的情況,url地址能夠唯一判別一個條數據的情況
- 思路
- url存在redis中
- 拿到url地址,判斷url在redis的url的集合中是夠存在
- 存在:說明url已經被請求過,不再請求
- 不存在:url地址沒有被請求過,請求,把該url存入redis的集合中
- 布隆過濾器
- 使用多個加密算法加密url地址,得到多個值
- 往對應值的位置把結果設置爲1
- 新來一個url地址,一樣通過加密算法生成多個值
- 如果對應位置的值全爲1,說明這個url地址已經抓過
- 否則沒有抓過,就把對應位置的值設置爲1
- 根據數據本省進行去重
- 選擇特定的字段,使用加密算法(md5,sha1)講字段進行假面,生成字符串,存入redis的集合中
- 後續新來一條數據,同樣的方法進行加密,如果得到的字符串在redis中存在,說明數據存在,對數據進行更新,否則說明數據不存在,直接插入
組成部分介紹:
- Scrapy Engine:
負責組件之間數據的流轉,當某個動作發生時觸發事件 - Scheduler:
接收requests,並把他們入隊,以便後續的調度 - Downloader:
負責抓取網頁,並傳送給引擎,之後抓取結果將傳給spider - Spiders:
用戶編寫的可定製化的部分,負責解析response,產生items和URL - Item Pipeline:
負責處理item,典型的用途:清洗、驗證、持久化 - Downloader middlewares:
位於引擎和下載器之間的一個鉤子,處理傳送到下載器的requests和傳送到引擎的response(若需要在Requests到達Downloader之前或者是responses到達spiders之前做一些預處理,可以使用該中間件來完成) - Spider middlewares:
位於引擎和抓取器之間的一個鉤子,處理抓取器的輸入和輸出
(在spiders產生的Items到達Item Pipeline之前做一些預處理或response到達spider之前做一些處理)