最詳細的Python爬蟲入門教程,一篇文章入門爬蟲不是兒戲!

来源:https://www.cnblogs.com/kongshouyisuiyue/archive/2018/09/05/9595424.html
-Advertisement-
Play Games

0×00 介紹 0×01 要求 0×02 你能學到什麼? 0×03 知識補充 0×04 最簡單的開始 0×05 更優雅的解決方案 0×06 url合法性判斷 0×07 總結與預告 0×00 介紹 學習Python中有不明白推薦加入交流群 號:548377875 群里有志同道合的小伙伴,互幫互助, 群 ...


 

最詳細的Python爬蟲入門教程,一篇文章入門爬蟲不是兒戲!

 

0×00 介紹

0×01 要求

0×02 你能學到什麼?

0×03 知識補充

0×04 最簡單的開始

0×05 更優雅的解決方案

0×06 url合法性判斷

0×07 總結與預告

0×00 介紹

學習Python中有不明白推薦加入交流群
號:548377875
群里有志同道合的小伙伴,互幫互助,
群里有不錯的學習教程!

爬蟲技術是數據挖掘,測試技術的重要的組成部分,是搜索引擎技術的核心。

最詳細的Python爬蟲入門教程,一篇文章入門爬蟲不是兒戲!

 

但是作為一項普通的技術,普通人同樣可以用爬蟲技術做很多很多的事情,比如:你想瞭解一下某網所有關於爬蟲技術的文章,你就可以編寫爬蟲去對文章進行搜索,解析。比如你想獲得淘寶某類商品的價格,你可以編寫爬蟲自動搜索某類商品,然後獲取信息,得到自己想要的結果,每天定時爬一下自己就可以決定在什麼時候低價的時候買下心儀的商品了。或者說自己想收集某類信息集合成自己的資料庫,但是手動複製粘貼特別的麻煩,這時候爬蟲技術就可以幫上大忙了對不對?

0×01 要求(私信小編007即可獲取大量Python學習資料)

 

那麼本系列文章旨在普及爬蟲技術,當然不是那種直接拿來爬蟲框架來說明的。在本系列文章中,筆者儘力從簡到難,簡明地介紹爬蟲的各種要素,怎麼樣快速編寫對自己有用的代碼。但是對讀者有一定小小的要求:看得懂python代碼,然後自己能動手實踐一些,除此之外,還要對html元素有一定的瞭解。

0×02 你能學到什麼?

當然爬蟲的文章在網上很容易找到,但是精緻,系統地講解的文章還是比較少,筆者在本文和今後的文章將介紹關於爬蟲的各種各樣的知識:

大致上,本文的寫作順序是單機爬蟲到分散式爬蟲,功能實現到整體設計,從微觀到巨集觀。

1. 簡單模塊編寫簡單爬蟲

2. 相對優雅的爬蟲

3. 爬蟲基本理論以及一般方法

4. 簡單Web數據挖掘

5. 動態web爬蟲(可以處理js的爬蟲)

6. 爬蟲的數據存儲

7. 多線程與分散式爬蟲設計

如果有讀者想找一些爬蟲的入門書籍來看,我推薦《web scraping with python》,這本書是英文版目前沒有中文譯本,但是網上有愛好者在翻譯,有興趣的讀者可以瞭解一下。

0×03 知識補充

在這裡的知識補充我其實是要簡單介紹目前主流的幾種爬蟲編寫用的模塊:

Htmllib(sgmllib),這個模塊是非常古老的一個模塊,偏底層,實際就是簡單解析html文檔而已,不支持搜索標簽,容錯性也比較差,這裡指的提醒的是,如果傳入的html文檔沒有正確結束的話,這個模塊是不會解析的,直到正確的數據傳入或者說強行關閉。

BeautifulSoup,這個模塊解析html非常專業,具有很好的容錯性,可以搜索任意標簽,自帶編碼處理方案。

Selenium,自動化web測試方案解決者,類似BeautifulSoup,但是不一樣的是,selenium自帶了js解釋器,也就是說selenium配合瀏覽器可以用來做動態網頁的爬取,分析,挖掘。

Scrapy框架:一個專業的爬蟲框架(單機),有相對完整的解決方案。

API爬蟲:這裡大概都是需要付費的爬蟲API,比如google,twitter的解決方案,就不在介紹。

筆者在文章中只會出現前三種方式來做爬蟲編寫。

0×04 最簡單的開始

最開始的一個例子,我將會先介紹最簡單的模塊,編寫最簡單的單頁爬蟲:

Urllib這個模塊我們這裡用來獲取一個頁面的html文檔,具體的使用是,

Web = urllib.urlopen(url)

Data = Web.read()

要註意的是,這是py2的寫法,py3是不一樣的。

Smgllib這個庫是htmllib的底層,但是也可以提供一個對html文本的解析方案,具體的使用方法是:

1. 自定義一個類,繼承sgmllib的SGMLParser;

2. 覆寫SGMLParser的方法,添加自己自定義的標簽處理函數

3. 通過自定義的類的對象的.feed(data)把要解析的數據傳入解析器,然後自定義的方法自動生效。

import urllib
import sgmllib

class handle_html(sgmllib.SGMLParser):
#unknown_starttag這個方法在任意的標簽開始被解析時調用
#tag為標簽名
#attrs表示標簽的參賽
def unknown_starttag(self, tag, attrs):
print "-------"+tag+" start--------"
print attrs
#unknown_endtag這個方法在任意標簽結束被解析時被調用
def unknown_endtag(self, tag):
print "-------"+tag+" end----------"

web =urllib.urlopen("http://freebuf.com/")
web_handler = handle_html()
#數據傳入解析器
web_handler.feed(web.read())

短短十幾行代碼,最簡單的單頁面爬蟲就完成了,以下是輸出的效果。我們可以看到標簽開始和結束都被標記了。然後同時列印出了每一個參數。

最詳細的Python爬蟲入門教程,一篇文章入門爬蟲不是兒戲!

 

 

接下來我們可以使用這種底層的解析方式來做個基礎的小例子:

下麵這個小例子在標簽開始的時候檢查標簽中的attrs屬性,解析出所有的參數的href屬性,知道的讀者都知道這基本是被一個爬蟲的必經之路。

import urllib
import sgmllib

class handle_html(sgmllib.SGMLParser):
defunknown_starttag(self, tag, attrs):
#這裡利用try與except來避免報錯。
#但是並不推薦這樣做,
#對於這種小腳本雖然無傷大雅,但是在實際的項目處理中,
#這種做法存在很大的隱患
try:
for attr in attrs:
if attr[0] == "href":
printattr[0]+":"+attr[1].encode('utf-8')
except:
pass

web =urllib.urlopen("http://freebuf.com/")
web_handler = handle_html()
web_handler.feed(web.read())

解析結果為:

最詳細的Python爬蟲入門教程,一篇文章入門爬蟲不是兒戲!

 

 

我們發現在解析出的href種,存在一些不和諧的因素,比如JavaScript的出現,比如其他功能變數名稱的出現,或者有些讀者說的,url有重覆。實際上,這是對於我們的FreeBuf站來說,但是對於互聯網上的各種複雜環境來說,上面的考慮是完全不夠的。關於這一點我們稍後再做討論。

但是筆者並不計劃就用這個方法來把我們的問題處理完全。因為我們有更優雅的解決方案。

0×05 更優雅的解決方案

當然我說的時BeautifulSoup,為什麼選用這個模塊呢?筆者私認為這個模塊解析html非常專業,這裡簡稱bs4,讀過bs4的讀者都很清楚。實際上beautifulsoup並不只是簡單的解析html文檔,實際上裡面大有玄機:五種解析器自動選擇或者手動指定,每個解析器的偏重方向都不一樣,有的偏重速度,有的偏重正確率。自動識別html文檔的編碼,並且給出非常完美的解決方案,支持css篩選,各種參數的方便使用。

BeautifulSoup的一般使用步驟:

1. 導入beatifulsoup庫 :from bs4 import BeautifulSoup

2. 傳入數據,建立對象: soup = BeautifulSoup(data),

3. 操作soup,完成需求解析。

下麵我們來看具體的代碼實例:

from bs4 import BeautifulSoup
import urllib
import re
web =urllib.urlopen("http://freebuf.com/")
soup = BeautifulSoup(web.read())
tags_a =soup.findAll(name="a",attrs={'href':re.compile("^https?://")})
for tag_a in tags_a:
printtag_a["href"]

這一段與sgmllib的第二短代碼相同功能,但寫起來就更加的優雅。然後還引入了正則表達式,稍微過濾下鏈接的表達式,過濾掉了JavaScript字樣,顯然看起來簡煉多了:

最詳細的Python爬蟲入門教程,一篇文章入門爬蟲不是兒戲!

 

 

簡單解釋一下上面的warning:

UserWarning: No parser was explicitlyspecified, so I’m using the best available HTML parser for this system(“html.parser”). This usually isn’t a problem, but if you run thiscode on another system, or in a different virtual environment, it may use adifferent parser and behave differently.

To get rid of this warning, change this:

BeautifulSoup([your markup])

to this:

BeautifulSoup([your markup],”html.parser”)

上面的內容是說:沒有特別指明解析器,bs4使用了它認為最好的解析器html.parser,這一般不會出問題,但是如果你在不同的環境下運行,可能解析器是不一樣的。要移除這個warning可以修改你的beautifulsoup選項改成BeautifulSoup(data, “html.parser”)

這個warning表明瞭bs4的自動選擇解析器來解析的特性。

0×06 url和合法性判斷

url與uri其實是一個東西,如果但是我們更多的不提uri,那麼我們來說一下關於url的處理:如果說像我們一開始那樣做的話,我們手動,或者通過正則去分析每一個url,我們要考慮url的各種結構,比如下麵這些例子:

path?ss=1#arch
http://freebuf.com/geek
?ss=1
path/me
javascript:void(0)
/freebuf.com/s/s/s/
sssfadea://ssss.ss
path?ss=1&s=1
ftp://freeme.com/ss/s/s
path?ss=1
#arch
//freebuf.com/s/s/s/
https://freebuf.com:443/geek?id=1#sid
//freebuf.com/s/s/s

我們大概就是要處理這麼多的不同形式的url,這些都是在網頁上非常有可能出現的url,那麼,那麼我們怎麼判斷這些的合法性呢?

先以//分開,左邊時協議+‘:’,右邊到第一個’/’是功能變數名稱,功能變數名稱後面時路徑,?後面時參數,#後面是錨點。

這麼分析來的話寫代碼判斷應該不是一個特別困難的事情,但是我們並沒有必要每次都去寫代碼解決這個問題啊,畢竟我們在使用python,這些事情並不需要自己來做,

其實我個人覺得這個要得益於python強大的模塊:urlparser,這個模塊就是把我們上面的url分析思路做了實現,用法也是pythonic:

import urlparse
url = set()
url.add('javascript:void(0)')
url.add('http://freebuf.com/geek')
url.add('https://freebuf.com:443/geek?id=1#sid')
url.add('ftp://freeme.com/ss/s/s')
url.add('sssfadea://ssss.ss')
url.add('//freebuf.com/s/s/s')
url.add('/freebuf.com/s/s/s/')
url.add('//freebuf.com/s/s/s/')
url.add('path/me')
url.add('path?ss=1')
url.add('path?ss=1&s=1')
url.add('path?ss=1#arch')
url.add('?ss=1')
url.add('#arch')
for item in url:
print item
o= urlparse.urlparse(item)
print o
print

然後執行代碼,我們可以看一下具體的解析結果:

import urlparse
url = set()
url.add('javascript:void(0)')
url.add('http://freebuf.com/geek')
url.add('https://freebuf.com:443/geek?id=1#sid')
url.add('ftp://freeme.com/ss/s/s')
url.add('sssfadea://ssss.ss')
url.add('//freebuf.com/s/s/s')
url.add('/freebuf.com/s/s/s/')
url.add('//freebuf.com/s/s/s/')
url.add('path/me')
url.add('path?ss=1')
url.add('path?ss=1&s=1')
url.add('path?ss=1#arch')
url.add('?ss=1')
url.add('#arch')
for item in url:
print item
o= urlparse.urlparse(item)
print o
printpath?ss=1#arch
ParseResult(scheme='', netloc='',path='path', params='', query='ss=1', fragment='arch')

http://freebuf.com/geek
ParseResult(scheme='http',netloc='freebuf.com', path='/geek', params='', query='', fragment='')

?ss=1
ParseResult(scheme='', netloc='', path='',params='', query='ss=1', fragment='')

path/me
ParseResult(scheme='', netloc='',path='path/me', params='', query='', fragment='')

javascript:void(0)
ParseResult(scheme='javascript', netloc='',path='void(0)', params='', query='', fragment='')

/freebuf.com/s/s/s/
ParseResult(scheme='', netloc='', path='/freebuf.com/s/s/s/',params='', query='', fragment='')

sssfadea://ssss.ss
ParseResult(scheme='sssfadea',netloc='ssss.ss', path='', params='', query='', fragment='')

path?ss=1&s=1
ParseResult(scheme='', netloc='',path='path', params='', query='ss=1&s=1', fragment='')

ftp://freeme.com/ss/s/s
ParseResult(scheme='ftp',netloc='freeme.com', path='/ss/s/s', params='', query='', fragment='')

path?ss=1
ParseResult(scheme='', netloc='',path='path', params='', query='ss=1', fragment='')

#arch
ParseResult(scheme='', netloc='', path='',params='', query='', fragment='arch')

//freebuf.com/s/s/s/
ParseResult(scheme='',netloc='freebuf.com', path='/s/s/s/', params='', query='', fragment='')

https://freebuf.com:443/geek?id=1#sid
ParseResult(scheme='https',netloc='freebuf.com:443', path='/geek', params='', query='id=1',fragment='sid')

//freebuf.com/s/s/s
ParseResult(scheme='',netloc='freebuf.com', path='/s/s/s', params='', query='', fragment='')

在urlparser返回的對象中我們可以直接以索引的方式拿到每一個參數的值。那麼我們這裡就有索引表了:

最詳細的Python爬蟲入門教程,一篇文章入門爬蟲不是兒戲!

 

這張表的用法,

o = urlparse.urlparse(url)

o[0]表示scheme

o[1]表示netloc

……

以此類推。

我們發現:

如果scheme和netloc都同時為空的話,該url可能是當前url+path

如果scheme不為空但是netloc為空的話,該url不合法

如果scheme為空但是netloc不為空的話,不一定不合法,要具體分析,一般情況下是http

如果只存在fragment或者query的話,該url為當前的url+query[+fragment]

……

那麼根據上面的規則,我們基本可以把無關的url或者不是url排除掉,或者恢復完整的url

0×07 總結與預告

本章中我們一起探究了一個簡單爬蟲的實現,然後稍微討論了一下如何處理頁面的url。相信讀者讀完本文的時候已經有了一定的對爬蟲的基礎認識,但是要知道,只瞭解到這種程度還不能說瞭解爬蟲,這隻是冰山一角。

在下一節中,我們將學到下麵的知識:

1、爬蟲道德與爬蟲的理論知識

2、sitemap爬蟲

3、簡單web數據處理

最詳細的Python爬蟲入門教程,一篇文章入門爬蟲不是兒戲!
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • liuyuhang原創,未經允許請勿轉載! 前端開發樹形插件帶來的煩惱(一) 前端開發中,有些項目中會用到樹形插件,其數據結構也比較簡單,大體如下: 數據結構說明: 每一行代表一個數據,該數據由基本信息,id,pid三個部分構成。pid為連接的父節點,額外增加的內容也包括兩個部分; ①縮進;②節點展 ...
  • spring知識的鞏固整理AOP和ioc概念,以及瞭解到了為何要使用spring框架的目的,作用:變換資源獲取的方向。更像是按需所求。配置bean的方式:利用XML的方式,基於註解的方式兩種。1通過全類名反射的方式,2通過工廠實例的方式,3 通過更底層的Beanfactory的方式依賴註入DI的方式 ...
  • 不知不覺中一年又走過了大半,不變的是技術依舊小白,唯一慶幸的是也沒有徹底停下腳步。 言歸正傳,今天總結記錄的是樓+學習中,挑戰一的兩個知識點。 1.from collections import namedtuple collections 是Python內建的一個集合模塊,提供了許多有用的集合類。 ...
  • 最近在項目中應用到springboot與mybatis,在進行整合過程中遇到一些坑,在此將其整理出來,便於以後查閱與複習。 項目運行環境為:eclispe+jdk1.8+maven 搭建Spring Boot環境 === 首先建立maven project,在生成的pom文件中加入依賴,代碼如下: ...
  • facebook atc介紹 Augmented Traffic Control(又名atc)是一種模擬網路狀況的工具。由facebook開源,是一個允許開發人員控制設備與互聯網連接的項目。atc可以模擬不同的網路條件,包括控制帶寬,延遲,數據包丟失、數據包損壞、數據包重排序等幾個因素都可以由atc ...
  • 線程池學習 以下所有內容以及源碼分析都是基於JDK1.8的,請知悉。 我寫博客就真的比較沒有順序了,這可能跟我的學習方式有關,我自己也覺得這樣挺不好的,但是沒辦法說服自己去改變,所以也只能這樣想到什麼學什麼了。 ​ 池化技術真的是一門在我看來非常牛逼的技術,因為它做到了在有限資源內實現了資源利用的最 ...
  • PHP生成一個六位數的邀請碼 $unique_no = substr(base_convert(md5(uniqid(md5(microtime(true)),true)), 16, 10), 0, 6); ...
  • 1.創建一個henan的空列表,添加zhengzhou,kaifeng,shangqiu,jiaozuo,xinyang元素; 2.在kaifeng元素前面插入一個luoyang元素; 3.把元素xinyang改成中文信陽; 4.在元素jiaozuo後面插入一個子列表[hebi,xuchang]; ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...