爬蟲學習筆記

爬蟲學習筆記

爬蟲的概念

模擬瀏覽器發起請求,獲取響應數據

爬蟲的流程

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
  • 能夠同時按照多個健將進行分組 {group:{_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之前做一些處理)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章