python3輕量級爬蟲

爲什麼是輕量級爬蟲?因爲複雜的爬蟲需要考慮的場景和問題非常的多,比如有些網頁需要登錄後才能訪問、而有些網頁使用javascript異步加載完成。輕量級爬蟲爬取的是不需要登錄的靜態網頁抓取。

一.爬蟲簡介

  • 爬蟲是一段自動抓取互聯網信息的程序,從一個url觸發訪問所關聯的所有url,並且從每個頁面中提取出有價值的數據。
  • 價值:互聯網數據,爲我所用。可以對數據進行分析,甚至可以基於數據做出自己的產品,比如更專業的新聞閱讀聚合器,最爆笑故事app,最漂亮美女圖片網,圖書對比價格網,python技術文章大全。

二.簡單爬蟲架構

首先需要一個爬蟲調度端,來啓動爬蟲、停止爬蟲、或者監視爬蟲的運行情況。在爬蟲架構中有三個模塊:

  • URL管理器:將要爬取的URL和已經爬取過的URL
  • 網頁下載器:將網頁下載下來存儲成一個字符串
  • 網頁解析器:解析字符串,一方面提取有價值的數據,另一方面提取訪問其他頁面的URL
調度器URL管理器下載器解析器應用有待爬URL?是/否獲取1個待爬取URLURL下載URL內容URL內容解析URL內容價值數據、新URL列表收集價值數據新增到待爬取URLloop[ 有待爬取URL? ]調度器URL管理器下載器解析器應用

三.URL管理器

管理待抓取URL集合和已抓取URL集合,防止重複抓取、循環抓取。

3.1 url管理器應具有的最小功能:

  • 添加新url到待爬取集合
  • 判斷待添加url是否在容器中
  • 判斷是否還有待爬取url
  • 獲取待爬取url
  • 將url從待爬取移動到已爬取

3.2 實現方式

  • 放在內存中set()集合。待爬取set(),已爬取set()
  • 存放在關係數據庫中urls(url,is_crawled)
  • 存放在緩存數據庫中,比如redis,本身支持set數據結構。大公司一般都使用緩存數據庫

四.網頁下載器

將互聯網上URL對應的網頁下載到本地的工具

  • urllib.request:直接的網頁下載,或者提交一些向網業輸入的數據,甚至支持需要登錄網頁的cookie處理,需要代理訪問的代理處理等。
  • requests:第三方包,提供更強大的功能

4.1 urllib簡單的獲取一個網頁。

爬取百度首頁就出錯。。。試了幾種方法,只有(‘gbk’,‘ignore’)有用,並且是偶爾正常顯示。爬取其他網頁就很順利,不知道是百度厲害,還是代碼太low。最終解決,在第一行添加如下代碼即可。。。不過也是是好是壞。


# -*- coding: UTF-8 -*- 
或
#coding=utf-8
  1. urlopen()參數
    • url: 需要打開的網址
    • data:Post提交的數據
    • timeout:設置網站的訪問超時時間,單位秒
  2. urlopen返回對象提供方法:
    • read() , readline() ,readlines() , fileno() , close() :對HTTPResponse類型數據進行操作
    • info():返回HTTPMessage對象,表示遠程服務器返回的頭信息
    • getcode():返回Http狀態碼。如果是http請求,200請求成功完成;404網址未找到
    • geturl():返回請求的url

4.2 使用Request

  • 用來包裝頭部的數據:
    • User-Agent :這個頭部可以攜帶如下幾條信息:瀏覽器名和版本號、操作系統名和版本號、默認語言
    • Referer:可以用來防止盜鏈,有一些網站圖片顯示來源http://***.com,就是檢查Referer來鑑定的
    • Connection:表示連接狀態,記錄Session的狀態。

4.3 添加特殊情景的處理

HTTPCookieProcessor,ProxyHandler,HTTPHandler,HTTPRedirectHandler生成handler

# -*- coding: UTF-8 -*-
import urllib.request
from http import cookiejar

url = "http://www.baidu.com"
print("第一種方法")
response1 = urllib.request.urlopen(url)
print(response1.getcode())
print(len(response1.read()))

print("第二種方法")
request=urllib.request.Request(url)
request.add_header("user-agent","Mozilla/5.0")
response2=urllib.request.urlopen(request)
print(response2.getcode())
print (len(response2.read()))


print("第三種方法")
cj=cookiejar.CookieJar()
opener=urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
urllib.request.install_opener(opener)
response3=urllib.request.urlopen(url)
print(response3.getcode())
print(cj)
print(response3.read())

五.網頁解析器

從網頁中提取有價值的數據的工具

  • 正則表達式,字符串匹配的模糊匹配,比較直觀,但是麻煩
  • html.parser自帶
  • Beautifulsoup插件,結構化解析-DOM樹
  • lxml插件

5.1 安裝beautifulsoup4

可以import bs4即安裝成功。查看官方文檔

5.2 beautifulsoup語法

創建Beautifulsoup對象,搜索節點find_all、find(參數一樣),訪問節點名稱、屬性、文字

例如:
<a href='123.html' class='article_link'>python</a>

節點名稱:a
節點屬性:href='123.html' class='article_link'
節點內容:python

#創建
soup = BeautifulSoup(html_cont, 'html.parser',from_encoding='utf-8')


#查找節點a
soup.find_all('a')
#查找節點a,鏈接符合/view/123.html形式的節點
soup.find_all('a',herf='/view/123.html')
soup.find_all('a',herf=re.compile(r'/view/\d+\.html'))#可以用正則表達式替代
#查找節點div,class爲abc,文字爲python的節點
node = soup.find_all('div',class_='abc', string='python')

#訪問節點信息
node.name #標籤名稱
node['href'] #標籤屬性
node.get_text() #文字內容

5.3 示例代碼:

# coding=utf8
from bs4 import BeautifulSoup
import re

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""

soup = BeautifulSoup(html_doc, 'html.parser')
print("打印所有內容")
links = soup.find_all('a')
for link in links:
    print(link.name, link['href'], link.get_text())

print("獲取lacie的連接")
link_node = soup.find('a',href="http://example.com/lacie")
print(link_node.name, link_node['href'], link_node.get_text())

print("正則匹配")
link_node = soup.find('a',href=re.compile(r"ill"))
print(link_node.name, link_node['href'], link_node.get_text())

print("獲取段落文字")
p_node = soup.find('p',class_="title")
print(p_node.name, p_node.get_text())

六.完整實例

  • 目標:抓取百度百科Python詞條相關的1000條頁面數據。
  • 分析目標:URL格式,數據格式,網頁編碼
  • 編寫代碼
  • 最後執行爬蟲

6.1 分析目標

- 目標:百度百科python詞條相關詞條網頁-標題和簡介
- 入口頁:https://baike.baidu.com/item/Python/407313
- url格式:/item/接口/15422203
- 數據格式:
    - 標題 <dd class="lemmaWgt-lemmaTitle-title"><h1>...</h1>...</dd>
    - 簡介 <div class="lemma-summary" label-module="lemmaSummary">...</div>
- 頁面編碼:UTF-8

查看代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章