小豬的Python學習之旅 —— 2.爬蟲初涉

引言html

本節開始學習Python爬蟲,爲何直接開始學爬蟲?由於實用性高啊, 練手項目多(那麼多網站能夠爬),後面還能夠作數據分析等等,還有最終 要的,能夠扒不少小姐姐到硬盤裏啊。什麼是爬蟲?個人理解: 模擬用戶使用瀏覽器請求網站,而後經過一些手段獲取到想要的信息; 好比在一個小網站上看到了不少漂亮的小姐姐圖片,你想把他們都存 到你的硬盤裏,天天沒事就拿出來把玩一下。python

若是你不會爬蟲,你只能重複地程序員

右鍵圖片->圖片另存爲->選擇文件夾->改下圖片名->保存正則表達式

呆得一匹,若是你學會了爬蟲,你只須要花幾分鐘編寫爬蟲腳本: 而後執行下Py腳本,你能夠去玩把跳一跳,回來就能夠看到小姐姐 們都乖乖地趟在你的硬盤裏了:chrome

對的,就是那麼酷炫,程序員就應該作些酷酷的事! 關於Python爬蟲,主要由兩個部分組成:json

  • 1.可以拿到正確的目標網站的網頁源碼
  • 2.經過一些技術手段拿到想要的目標信息

依次說下這兩個部分吧,先是拿到正確網頁源碼api

並非全部的源碼都是躺在那裏等你直接扒的,不少網站都會有 反爬蟲策略,好比:須要點擊閱讀全文才能加載全部內容;數據 使用Js動態生成(圖片站點尤多);這仍是不須要登陸的狀況,有些 站點須要登陸後才能訪問,模擬登陸驗證碼能夠卡死一堆人: 數字圖片模糊驗證計算數字運算驗證滑動條驗證滑動圖片驗證滑動壞塊完成拼圖驗證geetest那種人機驗證...瀏覽器

接着是經過技術手段拿到目標信息bash

這個倒沒什麼,最多也就是Js動態生成網頁,這個能夠經過後面學 的selenium來規避,反正瀏覽器顯示的是什麼樣,拿到的網頁源碼 就是怎麼樣。(還有一種噁心的:把文本數據寫到圖片上,讓你抓到 圖片也迫不得已,可使用ORC的一些庫進行文字識別,好比 tesseract-orc可是結果都是有些誤差的,還要本身另外處理...) 有正確的網頁源碼了,基本上都是找到咱們想要的數據的,學習 一些HTML,XML的解析庫就能夠了,好比:BeautifulSouplxml等, 隨便掌握一個就行了,筆者學習的是BeautifulSoup(甜湯)服務器

說下爬蟲學習路線吧:

1.先把基礎核心庫urllib學習一波; 2.接着學習一波BeautifulSoup來解析網頁數據; 3.學習正則表達式 4.使用Scrapy框架爬取數據 5.使用Selenium模擬瀏覽器 6.多線程抓取 等等...

關於爬蟲的基礎姿式就瞭解到這裏,開始本節內容~


1.urllib模塊詳解

用於操做URL的模塊(庫,py3把urllib和urllib2合併到了一塊兒) 爬網頁必須掌握的最基礎的東東。

1) 爬取網頁

import urllib.request
import urllib.parse
import json

# 爬取網頁信息
html_url = "http://www.baidu.com"
html_resp = urllib.request.urlopen(html_url)

# 讀取所有,讀取一行可用readline(),多行返回列表的可用readlines()
html = html_resp.read() 
html = html.decode('utf-8')  # 解碼
print(html)

# 得到其餘信息:
html_resp.info() # 得到頭相關的信息,HTTPMessage對象
html_resp.getcode() # 得到狀態碼
html_resp.geturl() # 獲取爬取的url

# url中包含漢字是不符合URL標準的,須要進行編碼
urllib.request.quote('http://www.baidu.com') 
# 編碼後:http%3A//www.baidu.com

urllib.request.unquote('http%3A//www.baidu.com') 
# 解碼後:http://www.baidu.com
複製代碼

2) 爬取二進制文件(圖片,音頻等)

# 下載圖片
pic_url = "http://static.zybuluo.com/coder-pig/agr9d5uow8r5ug8iafnl6dlz/1.jpg"
pic_resp = urllib.request.urlopen(pic_url)
pic = pic_resp.read()
with open("LeiMu.jpg", "wb") as f:
    f.write(pic)

# 也能夠直接調用urlretrieve下載,好比下載音頻
music_url = "http://7xl4pr.com2.z0.glb.qiniucdn.com/" \
            "%E4%B8%83%E7%94%B0%E7%9C%9F%E4%B8%93%E5%8C%BA%2F%E4%" \
            "B8%AD%E6%96%87%E8%AF%BE%2F%E6%83%B3%E8%" \
            "B1%A1%E7%82%B9%E5%8D%A1%2F%2B6.mp3"
urllib.request.urlretrieve(music_url, "兒歌.mp3")
複製代碼

3) 模擬Get請求與Post請求

PS:下面用到的**json模塊**:用於將Python原始類型與json類型相互轉換,使用 若是是讀取文件能夠用:dump()和load()方法,字符串的話用下述兩個:

dumps()編碼 [Python -> Json] dict => object      list, tuple => array      str => string      True => true int, float, int- & float-derived Enums => number      False => false     None => null

loads()解碼 [Json -> Python] object => dict     array => list     string => str     number (int) => int number(real) => float     true =>True     false => False     null => None

# 模擬Get
get_url = "http://gank.io/api/data/" + urllib.request.quote("福利") + "/1/1"
get_resp = urllib.request.urlopen(get_url)
get_result = json.loads(get_resp.read().decode('utf-8'))
# 這裏後面的參數用於格式化Json輸出格式
get_result_format = json.dumps(get_result, indent=2,
                               sort_keys=True,  ensure_ascii=False)
print(get_result_format)

# 模擬Post
post_url = "http://xxx.xxx.login"
phone = "13555555555"
password = "111111"
values = {
    'phone': phone,
    'password': password
}
data = urllib.parse.urlencode(values).encode(encoding='utf-8')
req = urllib.request.Request(post_url, data)
resp = urllib.request.urlopen(req)
result = json.loads(resp.read())    # Byte結果轉Json
print(json.dumps(result, sort_keys=True, 
                 indent=2, ensure_ascii=False)) # 格式化輸出Json
複製代碼

4) 修改請求頭

有些網站爲了不別人使用爬蟲惡意採起信息會進行一些反爬蟲的操做, 好比經過請求頭裏的User-Agent,檢查訪問來源是否爲正常的訪問途徑, 咱們能夠修改請求頭來進行模擬正常的訪問。Request中有個headers參數, 有兩種方法進行設置: 1.把請求頭都塞到字典裏,實例化Request對象的時候傳入 2.經過Request對象的add_header()方法一個個添加

# 修改頭信息
novel_url = "http://www.biqukan.com/1_1496/"
headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) '
                         'AppleWebKit/537.36 (KHTML, like Gecko)'
                         ' Chrome/63.0.3239.84 Safari/537.36',
           'Referer': 'http://www.baidu.com',
           'Connection': 'keep-alive'}
novel_req = urllib.request.Request(novel_url, headers=headers)
novel_resp = urllib.request.urlopen(novel_req)
print(novel_resp.read().decode('gbk'))
複製代碼

5) 設置鏈接超時

# urlopen函數時添加timeout參數,單位是秒
urllib.request.urlopen(novel_req, timeout=20)
複製代碼

6) 延遲提交數據

通常服務器會對請求的IP進行記錄,若是單位時間裏訪問的次數達到一個閥值, 會認爲該IP地址是爬蟲,會彈出驗證碼驗證或者直接對IP進行封禁。一個最簡單 的方法就是延遲每次提交的時間,直接用**time模塊sleep(秒)** 函數休眠下。

7) 代理

對應限制ip訪問速度的狀況咱們可使用延遲提交數據的作法, 可是有些是限制訪問次數的,同一個ip只能在一段時間裏訪問 多少次這樣,並且休眠這種方法效率也是挺低的。更好的方案是 使用代理,經過代理ip輪換去訪問目標網址。 用法示例以下:

# 使用ip代理
ip_query_url = "http://www.whatismyip.com.tw"

# 1.建立代理處理器,ProxyHandler參數是一個字典{類型:代理ip:端口}
proxy_support = urllib.request.ProxyHandler({'http': '221.214.110.130:8080'})
# 2.定製,建立一個opener
opener = urllib.request.build_opener(proxy_support)
# 3.安裝opener
urllib.request.install_opener(opener)

headers = {
    'User-Agent': 'User-Agent:Mozilla/5.0 (X11; Linux x86_64)'
                  ' AppleWebKit/537.36 (KHTML, like Gecko)'
                  ' Chrome/63.0.3239.84 Safari/537.36',
    'Host': 'www.whatismyip.com.tw'
}
MAX_NUM = 10    # 有時網絡堵塞,會報URLError錯誤,因此加一個循環
request = urllib.request.Request(ip_query_url, headers=headers)
for i in range(MAX_NUM):
    try:
        response = urllib.request.urlopen(request, timeout=20)
        html = response.read()
        print(html.decode('utf-8'))
        break
    except:
        if i < MAX_NUM - 1:
            continue
        else:
            print("urllib.error.URLError: <urlopen error timed out>")
複製代碼

輸出結果

如圖代理成功,這裏的網站是用於查詢請求ip的,另外,咱們通常會弄一個 代理ip的列表,而後每次隨機的從裏面取出一個來使用。

8) Cookie

Cookie定義:指某些網站爲了辨別用戶身份、進行 session 跟蹤而儲存在用戶本地終端上的數據(一般通過加密) 好比有些頁面你在登陸前是沒法訪問的,你登陸成功會給你分配 Cookie,而後你帶着Cookie去請求頁面才能正常訪問。 使用http.cookiejar這個模塊能夠幫咱們獲取Cookie,實現模擬登陸。 該模塊的主要對象(父類->子類): CookieJar –> FileCookieJar –>MozillaCookieJar與LWPCookieJar

由於暫時沒找到合適例子,就只記下關鍵代碼,後續有再改下例子:

# ============ 得到Cookie ============

# 1.實例化CookieJar對象
cookie = cookiejar.CookieJar()

# 2.建立Cookie處理器
handler = urllib.request.HTTPCookieProcessor(cookie)

# 3.經過CookieHandler建立opener
opener = urllib.request.build_opener(handler)

# 4.打開網頁
resp = opener.open("http://www.zhbit.com")

for i in cookie:
    print("Name = %s" % i.name)
    print("Name = %s" % i.value)
    
# ============ 保存Cookie到文件 ============
# 1.用於保存cookie的文件
cookie_file = "cookie.txt"

# 2.建立MozillaCookieJar對象保存Cookie
cookie = cookiejar.MozillaCookieJar(cookie_file)

# 3.建立Cookie處理器
handler = urllib.request.HTTPCookieProcessor(cookie)

# 4.經過CookieHandler建立opener
opener = urllib.request.build_opener(handler)

# 5.打開網頁
resp = opener.open("http://www.baidu.com")

# 6.保存Cookie到文件中,參數依次是:
# ignore_discard:即便cookies將被丟棄也將它保存下來
# ignore_expires:若是在該文件中cookies已存在,覆蓋原文件寫入
cookie.save(ignore_discard=True, ignore_expires=True)

# ============ 讀取Cookie文件 ============

cookie_file = "cookie.txt"

# 1.建立MozillaCookieJar對象保存Cookie
cookie = cookiejar.MozillaCookieJar(cookie_file)

# 2.從文件中讀取cookie內容
cookie.load(cookie_file, ignore_expires=True, ignore_discard=True)

handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
resp = opener.open("http://www.baidu.com")
print(resp.read().decode('utf-8'))

複製代碼

9) URL編解碼

對於url有時咱們須要進行編解碼,好比帶有中文的url,能夠調用:

urllib.request.quote(xxx) # 編碼
urllib.request.unquote(xxx) # 解碼
複製代碼

2.Beautiful Soup 庫詳解

1) 官方介紹

一個能夠從 HTMLXML 文件中提取數據的 Python庫,它可以經過 你喜歡的轉換器實現慣用的文檔導航、查找、修改文檔的方式。 Beautiful Soup 會幫你節省數小時甚至數天的工做時間。

簡單點說就是 爬取HTML和XML的利器

2) 安裝庫

PyCharm直接安裝File -> Default Settings -> Project Interpreter 選擇Python 3的版本 -> 點+號 -> 搜索beautifulsoup4 安裝便可

pip方法安裝的本身行百度,或者看上一節的內容~

3) 實例化BeautifulSoup對象

簡單點說這一步就是把html丟到BeautifulSoup對象裏,能夠是請求後的網站, 也能夠是本地的HTML文件,第二個參數是指定解析器,html.parser是內置的 html解析器,你還能夠用lxml.parser,不過要另外導庫。

網站:soup = BeautifulSoup(resp.read(), 'html.parser') 本地:soup = BeautifulSoup(open('index.html'),'html.parser')

另外還能夠調用**soup.prettify()**格式化輸出HTML

4) 四大對象

一.Tag(標籤)

查找的是:在全部內容中第一個符合要求的標籤,最經常使用的兩個東東: tag.name:得到tag的名字,好比body tag.attrs:獲取標籤內全部屬性,返回一個字典,能夠根據鍵取值,也能夠 直接調用get('xxx')拿到屬性。

還有個玩法是:能夠soup.body.div.div.a 這樣玩,同過加標籤名的形式 輕鬆獲取標籤的內容,不過查找的只是第一個!基本沒什麼卵用...

二.NavigableString(內部文字)

獲取標籤內部的文字,直接調用**.string**

三.BeautifulSoup(文檔的所有內容)

當作一個Tag對象就好,只是能夠分別獲取它的類型,名稱,一級屬性而已

四.Comment(特殊的NavigableString)

這種對象調用**.string來輸出內容會把註釋符號去掉**,直接把註釋裏的內容 打出來,須要加一波判斷:

if type(soup.a.string)==bs4.element.Comment:
    print soup.a.string  
複製代碼

5) 各類節點

PS:就是找到了目標節點附近的節點,而後順藤摸瓜找到目標節點。

子節點與子孫節點contents:把標籤下的全部子標籤存入到列表,返回列表 children:和contents同樣,可是返回的不是一個列表而是 一個迭代器,只能經過循環的方式獲取信息,類型是:list_iterator 前二者僅包含tag的直接子節點,若是是想扒出子孫節點,可使用descendants 會把全部節點都剝離出來,生成一個生成器對象<class 'generator'>

父節點與祖先節點 parent:返回父節點Tag parents:返回祖先節點,返回一個生成器對象

兄弟結點: 處於同一層級的結點,next_sibling下一個,previous_sibling 上一個,結點不存在返回None 全部兄弟節點next_siblingsprevious_sibling,返回一個生成器對象

先後結點next_elementprevious_element 全部先後結點next_elementsprevious_elements 返回一個生成器對象

6) 文檔樹搜索

最經常使用的方法

  • **find_all (self, name=None, attrs={}, recursive=True, text=None, limit=None, kwargs):

  • name參數:經過html標籤名直接搜索,會自動忽略字符串對象, 參數能夠是:字符串,正則表達式,列表,True或者自定義方法

  • keyword參數:經過html標籤的id,href(a標籤)和title,class要寫成class_, 能夠同時過濾多個,對於不能用的tags屬性,能夠直接用一個attrs字典包着, 好比:find_all(attrs={'data-foo': 'value'}

  • text:搜索文檔中的字符串內容

  • limit:限制返回的結果數量

  • recursive:是否遞歸檢索全部子孫節點

其餘方法

  • **find (self, name=None, attrs={}, recursive=True, text=None, kwargs): 和find_all做用同樣,只是返回的不是列表,而是直接返回結果。
  • find_parents()find_parent(): find_all() 和 find() 只搜索當前節點的全部子節點,孫子節點等. find_parents() 和 find_parent()用來搜索當前節點的父輩節點, 搜索方法與普通tag的搜索方法相同,搜索文檔搜索文檔包含的內容。
  • find_next_sibling()find_next_siblings(): 這2個方法經過 .next_siblings 屬性對當 tag 的全部後面解析的兄弟 tag 節點進行迭代, find_next_siblings() 方法返回全部符合條件的後面 的兄弟節點,find_next_sibling() 只返回符合條件的後面的第一個tag節點。
  • find_previous_siblings()find_previous_sibling(): 這2個方法經過 .previous_siblings 屬性對當前 tag 的前面解析的兄弟 tag 節點進行迭代, find_previous_siblings()方法返回全部符合條件的前面的 兄弟節點, find_previous_sibling() 方法返回第一個符合條件的前面的兄弟節點。
  • find_all_next()find_next(): 這2個方法經過 .next_elements 屬性對當前 tag 的以後的 tag 和字符串進行 迭代, find_all_next() 方法返回全部符合條件的節點, find_next() 方法返回 第一個符合條件的節點。
  • find_all_previous()find_previous() 這2個方法經過 .previous_elements 屬性對當前節點前面的 tag 和字符串 進行迭代, find_all_previous() 方法返回全部符合條件的節點, find_previous()方法返回第一個符合條件的節點

3.爬蟲實戰

1) 小說網站數據抓取下載txt到本地

上一節學習了基礎知識,這節又學了簡單的爬蟲姿式:urllib和Beautiful Soup庫, 確定是要來個實戰練練手的,選了個最簡單的並且有點卵用的小東西玩玩。 相信各位大佬平時都有看網絡小說的習慣吧,應該不多有老司機去會起點 付費看,通常都有些盜版小說網站,好比:筆趣看:www.biqukan.com/ 手機在線看,廣告是可怕的,想一想你在擠滿人的地跌上,忽然蹦出一對 柰子,你的第一反應確定是關掉,然而仍是naive,點X直接彈一個新的 網頁什麼壯陽延時...尷尬得一匹。學了Python爬蟲的東西了,寫個小爬蟲 爬爬小說順道練練手豈不美滋滋。不說那麼多,開搞: 我最近在看的小說:唐家三少的《斗羅大陸3-龍王傳說》 www.biqukan.com/1_1496/

圖中圈住的部分就是小說的章節,F12打開chrome的開發者工具,切到Network選項卡 (或者直接看Elements也行),選Response,刷新一波能夠看到這樣的HTML結構:

固然咱們要找的內容不在這裏,繼續往下翻:

listmain這個全局搜了下,是惟一的(好吧,找這個真的太沒難度了...) 直接find_all(attrs={'class': 'listmain'}) 就能夠拿到這段東西了 find_all返回一個bs4.element.ResultSet 對象,for循環遍歷一波 這個對象,(迭代對象的類型是**:bs4.element.Tag**)打印一波能夠看到:

咱們要留下的只是<a>xxx</a>這種東西,能夠在循環的時候順帶把 無關的篩選掉:

能夠打印下這個a_list,剩下的全是<a>xxx</a>

由於最新章節列表那裏默認有12個,咱們應該從楔子那裏開始, 因此把把a_list列表分下片:result_list = a_list[12:] 過濾掉前面的最新章節部分~

章節部分的數據就處理完畢了,有章節內容的url,以及章節的名稱, 接着咱們來看看章節頁面的內容結構,隨便打開一個: 好比:www.biqukan.com/1_1496/4503…

就不說了,class="showtxt"又是惟一的,直接: showtxt = chapter_soup.find_all(attrs={'class': 'showtxt'}) 把showtxt循環打印一波,裏面的東西就是咱們想要的東東了~

url有了,章節名有了,內容有了,是時候寫入到文件裏了,這個 過於簡單就不用多說了,strip=True表明刪除字符先後的全部空格:

到此咱們爬區小說的小爬蟲就寫完了,不過有個小問題是,批量 快速訪問的時候,會報503異常,由於服務器通常會對限制ip在 一段時間裏訪問的頻次,上面也講了要麼休眠,要麼搞ip代理, 確定是搞ip代理嗨一些,接着咱們來寫一個爬蟲來抓取西刺 代理的ip,並校驗是否可用,而後存到本地,咱們的代理ip池, 哈哈~

附上小說抓取這部分的代碼:

from bs4 import BeautifulSoup
import urllib.request
from urllib import error

novel_url = "http://www.biqukan.com/1_1496/"  # 小說頁面地址
base_url = "http://www.biqukan.com"  # 根地址,用於拼接

save_dir = "Novel/"  # 下載小說的存放路徑


# 保存小說到本地
def save_chapter(txt, path):
    try:
        with open(path, "a+") as f:
            f.write(txt.get_text(strip=True))
    except (error.HTTPError, OSError) as reason:
        print(str(reason))
    else:
        print("下載完成:" + path)


# 得到全部章節的url
def get_chapter_url():
    chapter_req = urllib.request.Request(novel_url)
    chapter_resp = urllib.request.urlopen(chapter_req, timeout=20)
    chapter_content = chapter_resp.read()
    chapter_soup = BeautifulSoup(chapter_content, 'html.parser')
    # 取出章節部分
    listmain = chapter_soup.find_all(attrs={'class': 'listmain'})
    a_list = []  # 存放小說全部的a標籤
    # 過濾掉不是a標籤的數據
    for i in listmain:
        if 'a' not in str(i):
            continue
        for d in i.findAll('a'):
            a_list.append(d)
    # 過濾掉前面"最新章節列表"部分
    result_list = a_list[12:]
    return result_list
    

# 獲取章節內容並下載
def get_chapter_content(c):
    chapter_url = base_url + c.attrs.get('href')  # 獲取url
    chapter_name = c.string  # 獲取章節名稱
    chapter_req = urllib.request.Request(chapter_url)
    chapter_resp = urllib.request.urlopen(chapter_req, timeout=20)
    chapter_content = chapter_resp.read()
    chapter_soup = BeautifulSoup(chapter_content, 'html.parser')
    # 查找章節部份內容
    showtxt = chapter_soup.find_all(attrs={'class': 'showtxt'})
    for txt in showtxt:
        save_chapter(txt, save_dir + chapter_name + ".txt")


if __name__ == '__main__':
    novel_list = get_chapter_url()
    for chapter in novel_list:
        get_chapter_content(chapter)


複製代碼

2) 抓取西刺代理ip並校驗是否可用

以前就說過了,不少服務器都會限制ip訪問的頻度或者次數,能夠經過設置代理 ip的方式來解決這個問題,代理ip百度一搜一堆,最出名的應該是西刺代理了: www.xicidaili.com/

爬蟲中代理ip使用得很是頻繁,每次都打開這個頁面粘貼複製,感受 過於低端,並且還有個問題,代理ip是會過時失效的,並且不必定 一直能夠用:要不來個這樣的騷操做:

寫個爬蟲爬取代理ip列表,而後校驗是否可用,把可用的存在本地, 下次須要代理的時候,讀取這個文件中的ip,放到一個列表中,而後 輪流切換ip或者經過random模塊隨機取出一個,去訪問目標地址。

抓取的網頁是:www.xicidaili.com/nn/1

Network選項卡,Response看下頁面結構,這裏我喜歡在PyCharm上 新建一個HTML文件,結點可摺疊,找關鍵位置代碼很方便:

如圖,不難發現就是咱們要找的內容,能夠從 find_all(attrs={'id': 'ip_list'}) 這裏入手,或者find_all('tr'),這裏有個小細節的地方首項是相似於表頭 的東西,咱們能夠經過列表分片去掉第一個:find_all('tr')[1:] 此時的列表:

接着就是要拿出ip和端口了,遍歷,先拿td,而後根據遊標拿數據:

數據都拼接成"ip:端口號"的形式了,而後就是驗證這個列表裏的代理 是否均可以用了,驗證方法也很簡單,直接設置代理而後訪問百度, 淘寶之類的網站,看返回碼是否爲200,是的話就表明代理可用,追加 到可用列表中,最後再把可用列表寫入到文件中:

而後你就有本身的代理ip池了,要用的時候讀取下文件就好,沒事更新一波文件~ 有了代理ip池,和上面扒小說的程序可用結合一波,應該就不會出現503的問題了, 具體有興趣的自行去完善吧(我懶...)

附上完整代碼:

from bs4 import BeautifulSoup
import urllib.request
from urllib import error

test_url = "https://www.baidu.com/"  # 測試ip是否可用
proxy_url = "http://www.xicidaili.com/nn/1"  # ip抓取源
ip_file = "availableIP.txt"


# 把ip寫入到文件中
def write_file(available_list):
    try:
        with open(ip_file, "w+") as f:
            for available_ip in available_list:
                f.write(available_ip + "\n")
    except OSError as reason:
        print(str(reason))


# 檢測代理ip是否可用,返回可用代理ip列表
def test_ip(test_list):
    available_ip_list = []
    for test in test_list:
        proxy = {'http': test}
        try:
            handler = urllib.request.ProxyHandler(proxy)
            opener = urllib.request.build_opener(handler)
            urllib.request.install_opener(opener)
            test_resp = urllib.request.urlopen(test_url)
            if test_resp.getcode() == 200:
                available_ip_list.append(test)
        except error.HTTPError as reason:
            print(str(reason))
    return available_ip_list


# 抓取西刺代理ip
def catch_ip():
    ip_list = []
    try:
        # 要設置請求頭,否則503
        headers = {
            'Host': 'www.xicidaili.com',
            'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36'
                          ' (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36'
        }
        req = urllib.request.Request(proxy_url, headers=headers)
        resp = urllib.request.urlopen(req, timeout=20)
        content = resp.read()
        soup = BeautifulSoup(content, 'html.parser')
        catch_list = soup.find_all('tr')[1:]

        # 保存代理ip
        for i in catch_list:
            td = i.find_all('td')
            ip_list.append(td[1].get_text() + ":" + td[2].get_text())

        return ip_list
    except urllib.error.URLError as reason:
        print(str(reason))


if __name__ == "__main__":
    xici_ip_list = catch_ip()
    available_ip_list = test_ip(xici_ip_list)
    write_file(available_ip_list)

複製代碼

結語

本節學習了urllib庫與Beautiful Soup,並經過兩個很是簡單的程序體驗了 一波爬蟲的編寫,順道溫習了下上節的基礎知識,美滋滋,比起Android 每天寫界面,有趣太多,本節的東西仍是小兒科,下節咱們來啃硬骨頭 正則表達式!敬請期待~


本節參考文獻


來啊,Py交易啊

想加羣一塊兒學習Py的能夠加下,智障機器人小Pig,驗證信息裏包含: PythonpythonpyPy加羣交易屁眼 中的一個關鍵詞便可經過;

驗證經過後回覆 加羣 便可得到加羣連接(不要把機器人玩壞了!!!)~~~ 歡迎各類像我同樣的Py初學者,Py大神加入,一塊兒愉快地交流學♂習,van♂轉py。

相關文章
相關標籤/搜索