天天看點

Python爬蟲基本庫的使用第二章 基本庫的使用

已寫章節

第一章 網絡爬蟲入門

第二章 基本庫的使用

第三章 解析庫的使用

第四章 資料存儲

第五章 動态網頁的抓取

文章目錄

      • 已寫章節
  • 第二章 基本庫的使用
    • 2.1 urllib庫的使用(非重點)
      • 2.1.1 request子產品
      • 2.1.2 error子產品
      • 2.1.3 parse子產品
    • 2.2 requests庫的使用(重點)
      • 2.2.1. requests庫的介紹
      • 2.2.2 requests庫的安裝
      • 2.2.3 requests庫的使用
        • 2.2.3.1 requests.get()方法
        • 2.2.3.2 requests.request()方法
        • 2.2.3.3 處理requests庫的異常
        • 2.2.3.4 發送POST請求
        • 2.2.3.5 requests庫的使用執行個體:TOP250電影資料、抓取二進制資料
    • 2.3 正規表達式(重點)
      • 2.3.1 正規表達式的介紹
      • 2.3.2 Re庫
        • 2.3.2.1 Re庫的介紹
        • 2.3.2.2 Re庫的使用
          • 2.3.2.2.1 re.match()方法
          • 2.3.2.2.2 使用分組
          • 2.3.2.2.3 通用比對和比對操作符
          • 2.3.2.2.4 貪婪與非貪婪
          • 2.3.2.2.5 控制标記
          • 2.3.2.2.6 re.search()
          • 2.3.2.2.7 re.findall()
          • 2.3.2.2.8 re.sub()
          • 2.3.2.2.9 re.compile()
      • 2.3.3 使用Re來爬取tx視訊

第二章 基本庫的使用

2.1 urllib庫的使用(非重點)

urllib的官方文檔

urllib是Python中自帶的HTTP請求庫,也就是說不用額外安裝就可以使用,它包含如下四個子產品:

  • requests:基本的HTTP請求子產品,可以模拟發送請求
  • error:異常處理子產品
  • parse:一個工具子產品,提供了許多URL處理方法,比如拆分、解析、合并等。
  • robotparser:它主要用來識别網站的robots.txt檔案,讓後判斷哪些内容可以爬取,哪些不能爬取,用得比較少。

2.1.1 request子產品

  • 發送請求
# 2.1 使用urllib庫中的request子產品發送一個請求的例子
import urllib.request

response = urllib.request.urlopen('http://www.baidu.com')
print(response.read().decode('utf-8'))
           

使用

request.urlopen()

來向百度首頁發起請求,傳回的是

http.client.HTTPResponse

對象,這個對象主要包含

read()

readinto()

getheader(name)

getheaders()

fileno()

等方法,以及

msg

version

status

reason

debuglevel

closed

等屬性。将傳回的HTML代碼以utf-8的編碼方式讀取并列印出來。上面的代碼執行後将傳回百度的首頁的HTML代碼。

我運作的效果如下:

<!DOCTYPE html><!--STATUS OK-->


    <html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta content="always" name="referrer"><meta name="theme-color" content="#2932e1"><meta name="description" content="全球最大的中文搜尋引擎、緻力于讓網民更便捷地擷取
資訊,找到所求。百度超過千億的中文網頁資料庫,可以瞬間找到相關的搜尋結果。">
後面省略無數字......
           

接下來再看這個例子:

# 2.2 使用urllib中的request子產品發起一個請求并擷取response對象中的資訊的例子
import urllib.request

response = urllib.request.urlopen("http://www.python.org")
print(response.read().decode('utf-8')[:100]) # 截取傳回的html代碼的前100個字元的資訊
print("response的類型為:" + str(type(response)))
print("response的狀态為:" + str(response.status))
print("response的響應的頭資訊:" + str(response.getheaders()))
print("response的響應頭中的Server值為:" + str(response.getheader('Server')))
           

上面的代碼使用

urlopen()

方法向指定的連結發起了一個請求,得到一個

HTTPResponse

對象,然後調用

HTTPResponse

的方法和屬性來擷取請求的狀态、請求頭資訊等

下面是我的執行結果:

<!doctype html>
<!--[if lt IE 7]>   <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9">   <![endif]-->
<!-
response的類型為:<class 'http.client.HTTPResponse'>
response的狀态為:200
response的響應的頭資訊:[('Connection', 'close'), ('Content-Length', '50890'), ('Server', 'nginx'), ('Content-Type', 'text/html; charset=utf-8'), ('X-Frame-Options', 'DENY'), ('Via', '1.1 vegur, 1.1 varnish, 1.1 varnish'), ('Accept-Ranges', 'bytes'), ('Date', 'Mon, 17 May 2021 08:59:57 GMT'), ('Age', '1660'), ('X-Served-By', 'cache-bwi5163-BWI, cache-hkg17920-HKG'), ('X-Cache', 'HIT, HIT'), ('X-Cache-Hits', '1, 3886'), ('X-Timer', 'S1621241997.260514,VS0,VE0'), ('Vary', 'Cookie'), ('Strict-Transport-Security', 'max-age=63072000; includeSubDomains')]
response的響應頭中的Server值為:nginx
           
  • data參數

data

參數是可選的,該參數是bytes類型,需要使用bytes()方法将字典轉化為位元組類型,并且,該參數隻能在POST請求中使用。

# 2.3 data參數的使用
import urllib.request

# 使用urllib中的parse子產品中的urlencode方法來将字典轉化為位元組類型,編碼方式為utf-8
data = bytes(urllib.parse.urlencode({'word': 'hello'}), encoding='utf8')
response = urllib.request.urlopen('http://httpbin.org/post', data=data)
print(response.read())
           

這次我們請求的是http://httpbin.org/post這個網址,這個網址可以提供http請求測試,它可以傳回請求的一些資訊,其中包括我們傳遞的data參數。

  • timeout參數

timeout

參數用來設定逾時時間,機關為秒,意思是如果請求超出了設定的這個時間,還沒有得到響應,就會抛出異常。

# 2.4 timeout參數的使用
import urllib.request

response = urllib.request.urlopen('http://www.baidu.com', timeout=1)
print(response.read())
           

運作結果就不展示了。

  • 其他參數

除了data參數和timeout參數外,還有context參數,它必須是ssl.SSLContext類型,用來指定SSL設定

Request類

urlopen()可以實作基本的請求的發起,但這不能構造一個完整的請求,如果要在請求中加入Headers等資訊,就可以利用更強大的Request類來建構。

# 2.5 Request類的使用
import urllib.request

request = urllib.request.Request('https://python.org')
print(type(request))
response = urllib.request.urlopen(request)   # 傳入的是Request對象
print(response.read().decode('utf-8'))
           

request的構造方法:

Requests(url, data, headers, origin_host, unverifiablem, method)
  • url:請求的url連結
  • data:必須為位元組流(bytes)類型
  • headers:請求頭資訊
  • origin_req_host:請求方的host名稱或者IP位址
  • unverifiable:表示這個請求是否是無法驗證的,預設為False。
  • method:訓示請求使用的方法,比如:GET、POST、PUT等

下面是例子:

# 2.6 Request類的使用
from urllib import request, parse

url = "http://httpbin.org/get"
headers = {
    'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
    'Host': 'httpbin.org'
}
dict = {
    'name': 'Germey'
}
data = bytes(parse.urlencode(dict), encoding='utf8')
req = request.Request(url=url, data=data, headers=headers, method='GET')
response = request.urlopen(req)
print(response.read().decode('utf-8'))
           

我們依然請求的是測試網址http://httpbin.org/get,它會傳回我們發起的請求資訊,下面是我的運作結果:

{
  "args": {}, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Content-Length": "11", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)", 
    "X-Amzn-Trace-Id": "Root=1-60a236ed-01f68c862b09c8934983ae80"
  }, 
  "origin": "221.176.140.213", 
  "url": "http://httpbin.org/get"
}
           

從結果中,我們可以看到我們發起的請求中包含了我們自己設定的User-Agent,Host和我們請求中包含的資料 ‘name’: ‘Germey’。

2.1.2 error子產品

urllib中的error子產品定義了由request子產品産生的異常,如果出現了問題,request子產品就會抛出error子產品中的異常。

下面介紹其中用得比較多的兩個異常:

URLError

HTTPError

  • URLError

    URLError類是error異常子產品的基類,由request子產品産生的異常都可以通過捕獲這個異常來處理。

    # 2.7 URLError的使用例子
    from urllib import request, error
    
    # 打開一個不存在的網頁
    try:
        response = request.urlopen('https://casdfasf.com/index.htm')
    except error.URLError as e:
        print(e.reason)
               
    運作結果:
    [Errno 11001] getaddrinfo failed
               
  • HTTPError

    它是URLError的子類,專門用來處理HTTP請求錯誤,比如認證請求失敗等。它有如下3個屬性:

    1. code:傳回HTTP狀态碼
    2. reason:傳回錯誤的原因
    3. headers:傳回請求頭
    # 2.8 HTTPError對象的屬性
    from urllib import request, error
    
    try:
        response = request.urlopen('https://cuiqingcai.com/index.htm')
    except error.HTTPError as e:
        print(e.reason, e.code, e.headers, sep='\n')
               
    運作結果:
    Not Found
    404
    Server: GitHub.com
    Date: Tue, 16 Feb 2021 03:01:45 GMT
    Content-Type: text/html; charset=utf-8
    X-NWS-UUID-VERIFY: 8e28a376520626e0b40a8367b1c3ef01
    Access-Control-Allow-Origin: *
    ETag: "6026a4f6-c62c"
    x-proxy-cache: MISS
    X-GitHub-Request-Id: 0D4A:288A:10EE94:125FAD:602B33C2
    Accept-Ranges: bytes
    Age: 471
    Via: 1.1 varnish
    X-Served-By: cache-tyo11941-TYO
    X-Cache: HIT
    X-Cache-Hits: 0
    X-Timer: S1613444506.169026,VS0,VE0
    Vary: Accept-Encoding
    X-Fastly-Request-ID: 9799b7e3df8bdc203561b19afc32bb5803c1f03c
    X-Daa-Tunnel: hop_count=2
    X-Cache-Lookup: Hit From Upstream
    X-Cache-Lookup: Hit From Inner Cluster
    Content-Length: 50732
    X-NWS-LOG-UUID: 5426589989384885430
    Connection: close
    X-Cache-Lookup: Cache Miss
               

2.1.3 parse子產品

parse子產品是用來處理url的子產品,它可以實作對url各部分的抽取、合并以及連接配接裝換等。

下面介紹parse子產品中常用的幾個方法:

  • urlparse()

    實作url的識别和分段

    # 2.9 urllib庫中parse子產品中urlparse()方法的使用
    from urllib.parse import urlparse
    
    result = urlparse('http://www.biadu.com/index.html;user?id=5#comment')
    print(type(result), result)
    
    result1 = urlparse('www.biadu.com/index.html;user?id=5#comment', scheme='https')
    print(type(result1), result1)
    
    result2 = urlparse('http://www.baidu.com/index.html#comment', allow_fragments=False)
    print(type(result2), result2)
    
    result3 = urlparse('http://www.baidu.com/index.html#comment', allow_fragments=False)
    print(result3.scheme, result3[0], result3.netloc, result3[1], sep="\n")
               
    運作結果:
    <class 'urllib.parse.ParseResult'> ParseResult(scheme='http', netloc='www.biadu.com', path='/index.html', params='user', query='id=5', fragment='comment')
    <class 'urllib.parse.ParseResult'> ParseResult(scheme='https', netloc='', path='www.biadu.com/index.html', params='user', query='id=5', fragment='comment')
    <class 'urllib.parse.ParseResult'> ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html#comment', params='', query='', fragment='')
    http
    http
    www.baidu.com
    www.baidu.com
               
    可以看到,urlparse()方法将url解析為6部分,傳回的是一個ParseResult對象,這6部分是:
    1. scheme:😕/前面的部分,指協定
    2. netloc:第一個/的前面部分,指域名
    3. path:第一個/後面的部分,指通路路徑
    4. params:;後面的部分,指參數
    5. query:問号後面的内容,指查詢條件
    6. fragment:#号後面的内容,值錨點
    是以,可以得出一個标準的連結格式:
    scheme://netloc/path;params?query#fragment

    一個标準的URL都會符合這個規則,我們就可以使用urlparse()這個方法來将它拆分開來。

    urlparse()方法還包含三個參數:

    urlstring:必選項,即待解析的URL

    scheme:預設協定,假如這個連結沒有帶協定資訊,會将這個作為預設的協定。

    allow_fragments:即是否忽略fragment。如果它被設定為false,fragment就會被忽略,它會被解析為path、params或者query的一部分,而fragment部分為空

  • urlunparse()

    它和urlparse()方法相反,它接收的參數是一個可疊代對象(常見的有清單、數組、集合),它的長度必須為6。

    # 2.10 parse子產品中的urlparse方法的使用
    from urllib.parse import urlunparse
    
    data = ['http', 'www.baidu.com', 'index.html', 'user', 'a=6', 'comment']
    print(urlunparse(data))
               
    上面的例子中傳入的是一個包含6個元素的清單,當然可以是其他類型,如元組,隻需要這個可疊代對象的長度為6個就可以了。
  • urlsplit()

    和urlparse()方法相似,隻不過它不再單獨解析params這一部分,而将params加入到path中,隻傳回5個結果

    # 2.11 parse子產品中的urlsplit方法的使用
    from urllib.parse import urlsplit
    
    result = urlsplit('http://www.baidu.com/index.html;user?id=5#comment')
    print(result)
               
    運作結果:
    SplitResult(scheme='http', netloc='www.baidu.com', path='/index.html;user', query='id=5', fragment='comment')
               
  • urlunsplit()

    和urlsplit()方法相反,傳入的參數也是一個可疊代的對象,例如清單、元組等,長度必須為5。

    # 2.12 parse子產品中的urlunsplit方法的使用
    from urllib.parse import urlunsplit
    
    data = ['http', 'www.baidu.com', 'index.html', 'a=6', 'comment']
    print(urlunsplit(data))
               
    運作結果:
    http://www.baidu.com/index.html?a=6#comment
               
  • urljoin()

    該方法接收兩個參數,一個是base_url,另外一個是新的url,該方法會分析新url中的scheme、netloc、path三部分的内容是否存在,如果某個不存在,就用base_url中的來替換。

  • urlencode()

    将字典類型轉換為url中的參數

    # 2.13 parse子產品中的urlencode方法的使用
    from urllib.parse import urlencode
    params = {
        'name': 'germey',
        'age': '22'
    }
    base_url = 'http://www.baidu.com?'
    url = base_url + urlencode(params)
    print(url)
               
    運作結果:
    http://www.baidu.com?name=germey&age=22
               
  • parse_qs()、parse_qsl()

    parse_qs:反序列化,将get請求參數轉化為字典

    parse_qsl:反序列化,将get參數轉化為元組組成的字典

    # 2.14 parse子產品中parse_qs和parse_qsl方法的使用
    from urllib.parse import parse_qs, parse_qsl
    
    # 反序列化,将參數轉化為字典類型
    query = 'name=germey&age=22'
    print(parse_qs(query))
    
    # 反序列化,将參數轉化為元組組成的清單
    print(parse_qsl(query))
               
    運作結果:
    {'name': ['germey'], 'age': ['22']}
    [('name', 'germey'), ('age', '22')]
               
  • quote()、unquote()

    quote:将内容轉化為URL編碼的格式,URL中帶有中文參數時,有可能會導緻亂碼的問題,用這個方法就可以将中文字元轉化為URL編碼。

    unquote:和quote()方法相反,将URL解碼

    # 2.15 parse子產品中quote()方法和unquote()方法的使用
    from urllib.parse import quote, unquote
    
    keyword = '書包'
    url = 'https://www.baidu.com/?wd=' + quote(keyword)
    print(url)
    
    url = 'https://www.baidu.com/?wd=%E5%A3%81%E7%BA%B8'
    print(unquote(url))
               
    運作結果:
    https://www.baidu.com/?wd=%E4%B9%A6%E5%8C%85
    https://www.baidu.com/?wd=桌面
               

urllib中的robotparse子產品可以實作robots協定的分析,用得不多,這裡就不再介紹。

2.2 requests庫的使用(重點)

學習爬蟲,最基礎的便是模拟浏覽器向伺服器送出請求。

requests文檔

2.2.1. requests庫的介紹

利用Python現有的庫可以非常友善的實作網絡請求的模拟,常見的有urllib、requests等。requests子產品是Python原生的一款基于網絡請求的子產品,功能非常強大,效率極高。

作用:模拟浏覽器發起請求

2.2.2 requests庫的安裝

requests庫是Python的第三方庫,需要額外安裝,在cmd中輸入以下代碼使用pip安裝:

pip install requests

2.2.3 requests庫的使用

要檢查是否已經正确安裝requests庫,在編輯器或Python自帶的IDLE中導入requests庫:

import requests
           

執行後沒有發生錯誤就說明你已經正确安裝了requests庫。

也可以在cmd指令行視窗中輸入:

pip list

後按回車,就會顯示所有pip已安裝的第三方庫,在清單中看到request庫就表明成功安裝requests庫。

下面介紹Requests庫的7個主要方法:

方法 介紹
requests.request() 構造一個請求,支撐以下的各種基礎方法,不常用
requests.get() 擷取HTML網頁的主要方法,對應于HTTP的GET,常用
requests.head() 擷取HTML網頁頭資訊的方法,對應于HTTP的
requests.post() 向HTML頁面送出POST請求的方法,對應于HTTP的POST
requests.put() 向HTM頁面送出PUT請求的方法,對應于HTTP的PUT
requests.patch() 向HTML頁面送出局部修改請求,對應于HTTP的PATCH
requests.delete() 向HTML頁面送出删除請求,對應于HTTP的DELETE

2.2.3.1 requests.get()方法

requests.get(url, params=None, **kwargs)
  • url : 要擷取頁面的url連結,必選
  • params :url中的額外參數,字典或位元組流格式,可選
  • **kwargs : 12個控制通路的參數,可選

我們在浏覽器中輸入一個url後按下enter,其實是發起一個get請求。同樣,使用requests庫發起一個get請求,可以使用requests庫下的get()方法,requests.get()方法可以構造一個向伺服器請求資源的Request對象并傳回一個包含伺服器資源的Response對象。request對象和response對象是requests庫中的2個重要對象,response對象包含伺服器傳回的所有資訊,也包含請求的request資訊,下面是response對象的屬性:

屬性 說明
r.status_code HTTP請求的傳回狀态,200表示成功,404表示失敗
r.text HTTP響應内容的字元串形式,即url對應的頁面内容
r.encoding 從HTTP header中猜測的響應内容編碼方式,如果header中不存在charset,則認為編碼為ISO-8859-1,r.text根據r.encoding顯示網頁内容
r.apparent_encoding 從内容中分析出的響應内容的編碼方式(備用編碼方式,一般比較準确)
r.content HTTP響應内容的二進制形式

下面是一個使用requests.get()方法通路百度并列印出傳回的response對象的各種屬性的例子:

import requests

# 2.16 使用requests.get()方法發送一個get()請求
r = requests.get("https://www.baidu.com")
print("r的狀态碼為:", r.status_code)
print("r的内容為:", r.text)
print("從r的header中推測的響應内容的編碼方式為:", r.encoding)
print("從r的内容中分析出來的響應内容編碼方式為:", r.apparent_encoding)
print("r内容的二進制形式為:", r.content)
           

2.2.3.2 requests.request()方法

requests.request(method, url, **kwargs)
  • method : 請求方式,對應get/put/post/head/patch/delete/options7種
  • url : 要擷取頁面的url連結
  • **kwargs : 控制通路的參數,共13個

**kwargs:控制通路的參數,都為可選項:

控制通路參數 說明
params 字典或位元組序列,作為參數增加到url中
data 字典、位元組序列或檔案對象,作為request的内容
json JSON格式的資料,作為request的内容
headers 字典,HTTP定制頭
cookies 字典或cookieJar,Request中的cookie
auth 元組,支援HTTP認證功能
files 字典類型,傳輸檔案
timeout 設定逾時時間,秒為機關
proxies 字典類型,設定代理伺服器,可以增加登入認證
allow_redirects True/False,預設為True,重定向開關
stream True/False,預設為True,擷取内容立即下載下傳開關
verify True/False,預設為True,認證SSL證書開關
cert 本地SSL證書路徑

下面隻介紹幾個常用的參數。

params:字典或位元組序列,作為參數增加到url中

import requests

# 2.17 請求參數params參數的使用
kv = {"key1": "value1", "key2": "value2"}
r = requests.request('GET', 'http://httpbin.org/get', params=kv)
# 也可寫成: r = requests.get('http://httpbin.org/get', params=kv)
print(r.url)
print(r.text)
           

如果向網站http://httpbin.org/get發起一個get請求,該網站會将你的請求頭的資訊傳回回來。

print(r.url)

将輸出:

http://httpbin.org/get?key1=value1&key2=value2,

可以看到,已經将字典作為參數增加到url中了!

同時上面的代碼

print(r.text)

也将請求放回的資訊也列印出來了:

{

“args”: {

“key1”: “value1”,

“key2”: “value2”

},

“headers”: {

“Accept”: “/”,

“Accept-Encoding”: “gzip, deflate”,

“Host”: “httpbin.org”,

“User-Agent”: “python-requests/2.24.0”,

“X-Amzn-Trace-Id”: “Root=1-600f8cf4-6af557655f1c1a771135e7fb”

},

“origin”: “117.150.137.110”,

“url”: “http://httpbin.org/get?key1=value1&key2=value2”

}

上面就是我們發起的請求的相關資訊,有請求頭、發起請求的浏覽器、參數等。

data:字典、位元組序列或檔案對象,作為request的内容

import requests

# 2.18 請求參數data的使用
data = 'data'
r = requests.request('POST', 'http://httpbin.org/post', data=data)
# 也可寫成: r = requests.post('http://httpbin.org/post', data=data)
# 這發起的是POST請求,可以看3.4
print(r.text)
           

我執行後的結果:

{

“args”: {},

“data”: “data”,

“files”: {},

“form”: {},

“headers”: {

“Accept”: “/”,

“Accept-Encoding”: “gzip, deflate”,

“Content-Length”: “4”,

“Host”: “httpbin.org”,

“User-Agent”: “python-requests/2.24.0”,

“X-Amzn-Trace-Id”: “Root=1-600f8f3d-46564aa85b91258f2d1c7511”

},

“json”: null,

“origin”: “117.150.137.110”,

“url”: “http://httpbin.org/post”

}

可以看到,"data"已經作為request的内容了。

json:JSON格式的資料,作為request的内容

import requests

# 2.19 請求參數json的使用
kv = {'key1':'value1'}
r = requests.request('POST', 'http://httpbin.org/post', json=kv)
# 也可寫成:r = requests.post('http://httpbin.org/post', json=kv)
print(r.text)
           

我執行後的結果:

{

“args”: {},

“data”: “{“key1”: “value1”}”,

“files”: {},

“form”: {},

“headers”: {

“Accept”: “/”,

“Accept-Encoding”: “gzip, deflate”,

“Content-Length”: “18”,

“Content-Type”: “application/json”,

“Host”: “httpbin.org”,

“User-Agent”: “python-requests/2.24.0”,

“X-Amzn-Trace-Id”: “Root=1-600f8f00-2419855b4f772b4851c12cdd”

},

“json”: {

“key1”: “value1”

},

“origin”: “117.150.137.110”,

“url”: “http://httpbin.org/post”

}

headers:字典、HTTP定制頭

請求頭Headers提供了關于請求、響應或其他發送實體的資訊。對于爬蟲而言,請求頭非常重要,有很多網站會通過檢查請求頭來判斷請求是不是爬蟲發起的。

那如何找到正确的Headers呢?

在Chrome中或其他浏覽器打開要請求的網頁,右擊網頁任意處,在彈出的菜單中單擊“檢查"選項,

Python爬蟲基本庫的使用第二章 基本庫的使用

點選Network,點選下面的資源清單中的任意一個,我點選的是第一個,在右邊彈出的界面中找到Requests Headers,就可以看到Requests Headers中的詳細資訊:

Python爬蟲基本庫的使用第二章 基本庫的使用

我們将Requests Headers中的user-agent對應的資訊複制下來,用在下面的代碼中:

import requests

# 2.20 請求參數headers的使用
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'}
r = requests.request('POST', 'http://httpbin.org/post',headers=headers)
# 也可寫成: r = requests.post('http://httpbin.org/post',headers=headers)
print(r.text)
           

我的運作結果:

{

“args”: {},

“data”: “”,

“files”: {},

“form”: {},

“headers”: {

“Accept”: “/”,

“Accept-Encoding”: “gzip, deflate”,

“Content-Length”: “0”,

“Host”: “httpbin.org”,

“User-Agent”: “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36”,

“X-Amzn-Trace-Id”: “Root=1-600f9f2f-016953bc4635251a20212054”

},

“json”: null,

“origin”: “117.150.137.110”,

“url”: “http://httpbin.org/post”

}

可以看到,我們的請求頭中的user-Agent已經變成我們自己構造的了!

timeout:設定逾時時間,秒為機關

import requests

# 2.21 請求參數timeout的使用
r = requests.request('GET', 'http://www.baidu.com', timeout=10)
# 也可寫成: r = requests.request('http://www.baidu.com', timeout=10)
           

proxies:字典類型,設定通路代理伺服器,可以增加代理驗證

import requests

# 2.22 請求參數proxies的使用
pxs = {
    'http': 'http://user:[email protected]:12344'
    'https': 'https://10.10.10.1.12344'
}
r = requests.request('GET', 'http://www.baidu.com', proxies=pxs)
# 也可寫成: r = requests.get('http://www.baidu.com', proxies=pxs)
           

cookies: 字典或cookieJar,Request中的cookie

首先看一下擷取cookie的過程:

import requests

# 2.23 請求參數cookies的使用
r = requests.request('GET', 'https://www.baidu.com')
# 也可寫成: r = requests.get('https://www.baidu.com')
print(r.cookies)

for key, value in r.cookies.items():
    print(key + '=' + value)
           

運作結果如下:

<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>

BDORZ=27315

第一行是直接列印的cookie資訊,我們發現它是RequestCookieJar類型。第二行是周遊的Cookie的資訊。

我們也可以使用Cookie來保持登入狀态,以登入百度為例,首先,登入百度,讓後用上面我教你的方法來擷取Requests Headers中的user-agent和cookie的資訊,将它們設定到Headers中,然後發送請求:

import requests

# 2.24 使用cookies的執行個體
headers = {
    'Cookie': 'BIDUPSID=A41FB9F583DE46FF509B8F9443183F5C;\
              PSTM=1604237803; BAIDUID=A41FB9F583DE46FF6179FBA5503669E3:FG=1;\
              BDUSS=jdRb3ZMQTR5OX5XYTd1c0J3eUVSWGVlRVgxZ0VlMjRFR3dGMkZZMDlMNWR\
              3eWRnRVFBQUFBJCQAAAAAABAAAAEAAACzkIz7vfDP~rarMzIxAAAAAAAAAAAAAAAAAA\
              AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF02AGBdNgBgW;\
               BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; H_PS_PSSID=33425_33437_33344_\
               31253_33284_33398_33459_26350; delPer=0; PSINO=3; BD_HOME=1; BD_UPN=123\
               14753; BA_HECTOR=2k808k8h0000a18g001g0v9e80r',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, \
                  like Gecko) Chrome/88.0.4324.96 Safari/537.36 Edg/88.0.705.50'
}
r = requests.request('GET', "https://www.baidu.com", headers=headers)
# 也可以寫成  r = requests.get("https://www.baidu.com", headers=headers)
print(r.text)
           

這樣,我們就實作了用Python模拟登入到百度了,結果中包含我們隻有登入百度後才能檢視的資訊。

2.2.3.3 處理requests庫的異常

在上面的代碼中,r=requests.get(“https://www.baidu.com”),并不是在任何時候都會成功,如果連結打錯或通路的連結不存在,則會産生異常。下面列出了常見的異常:

異常 說明
requests.ConnectionError 網絡連結錯誤,入DNS查詢失敗,拒絕連結等
requests.HTTPError HTTP錯誤異常
requests.URLRequired URL缺失異常
requests.TooManyRedirects 超過最大重定向次數,産生重定向異常
requests.ConnectionTimeout 連結遠端伺服器逾時異常
requests.Timeout 請求URL逾時,産生逾時異常

處理異常,可以使用

requests.raise_for_status()

方法,該方法在其内部判斷r.status_code是否等于200,不需要增加額外的if語句:

import requests

# 2.25 處理發送請求過程中的異常
try:
    # 下面的連結錯了,将列印輸出"參數異常"
    r = requests.get("https://www.baidu.co")
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    print(r.text)
except:
    print("産生異常")
           

2.2.3.4 發送POST請求

除了GET請求外,有時還需要發送一些編碼為表單形式的資料,如在登入的時候請求就為POST,因為如果使用GET請求,密碼就會顯示在URL中,這是非常不安全的。如果要實作POST請求,其實在上面的介紹requests.request( )方法時就已經實作了,你也可以看看下面用requests.post()方法實作的代碼,對比後發現,requests.post()方法其實就是将requests.request(‘POST’, …)方法給包裝起來了,這也是為什麼說requests.request()方法是實作其他方法的基礎了,上面的例子中也建議大家不用requests.request()方法。

import requests

# 2.26 發送POST請求
key_dict = {'key1':'value1', 'key2': 'value2'}
r = requests.post('http://httpbin.org/post', data=key_dict)
# 也可寫成: r = requests.request('POST', 'http://httpbin.org/post', data=key_dict)
print(r.text)
           

按照上面的requests.request()方法的13個通路參數,你就會将其應用到requests.get()或requests.post()方法中了吧!在來看一個例子:

import requests

r = requests.get('http://www.baidu.con', timeout=3)
print(r.text)
           

2.2.3.5 requests庫的使用執行個體:TOP250電影資料、抓取二進制資料

打開豆瓣電影TOP250的網站,右鍵滑鼠,使用“檢查"功能檢視該網頁的請求頭:

Python爬蟲基本庫的使用第二章 基本庫的使用

按照下面提取請求頭中的重要資訊:

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36 Edg/88.0.705.50',
    'Host': 'movie.douban.com'
}

           

使用這個headers構造請求頭并爬取前25個電影的名稱,提取部分的代碼大家看不懂沒關系,大家隻要看懂請求發起代碼的實作:

import requests
from bs4 import BeautifulSoup

# 2.27 發送get請求爬取豆瓣電影的前25個電影
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36 Edg/88.0.705.50',
    'Host': 'movie.douban.com'
}
r = requests.get('https://movie.douban.com/top250', headers=headers, timeout=10)
try:
    r.raise_for_status()
    soup = BeautifulSoup(r.text, 'html.parser')
    movies = soup.find_all('div', {'class': 'hd'})
    for each in movies:
        print(each.a.span.text.strip())
except:
    print("error")
           

執行後将輸出:

肖申克的救贖

霸王别姬

阿甘正傳

這個殺手不太冷

下面是一個抓取favicon.ico圖示的例子:

import requests

# 2.28 發送get請求爬取圖檔
r = requests.get('https://github.com/favicon.ico')
with open('favicon.ico', 'wb') as f:
    f.write(r.content)
           

運作結束後,檔案夾中将出現名為favicon.ico的圖示。上面的代碼先使用get方法發起一個get請求,讓後将請求傳回的内容以wb(二進制)寫入favicon.ico檔案中。

2.3 正規表達式(重點)

2.3.1 正規表達式的介紹

本節中,我們看一下正規表達式的相關用法。正規表達式是處理字元串的強大工具,它有自己特定的文法結構,有了它,實作字元串的檢索、替換、比對驗證都不在話下。

正規表達式是用來簡介表達一組字元串的表達式,正規表達式是一種通用的字元串表達架構。正規表達式可以用來判斷某字元串的特征歸屬。

在爬蟲中,我們使用它來從HTML中提取想要的資訊就非常友善了。

例如:正規表達式:

p(Y|YT|YTH|YTHO)?N

它可以表示:

  • ‘PN’
  • ‘PYN’
  • ‘PYTN’
  • ‘PYTHN’
  • ‘PYTHON’

這5個字元串。

正規表達式文法由字元和操作符構成,上面的例子中的() | ? 都是操作符,其他的是字元。

下面是正規表達式的常用的操作符:

操作符 說明 執行個體
. 表示任何單個字元,除了換行符
[ ] 字元集,對單個字元給出取值範圍 [abc]表示a、b、c,[a-z]表示a到z單個字元
[^ ] 非字元集,對單個字元給出排除範圍 [^abc]表示非a非b非c的單個字元
* 前一個字元0次或無限次擴充 abc*表示ab、abc、abcc、abccc等
+ 前一個字元1次或無限次擴充 abc+表示abc、abcc、abccc等
前一個字元0次或1次擴充 abc?表示ab、abc
| 左右表達式中任意一個 abc|def表示abc、def
{m} 擴充前一個字元m次 ab{2}c表示abbc
{m, n} 擴充前一個字元m至n次(含n) ab{1,2}c表示abc、abbc
^ 比對字元串開頭 ^abc表示abc且在一個字元串的開頭
$ 比對字元串結尾 abc$表示abc且在一個字元的結尾
( ) 分組标記,内部隻能使用|操作符 (abc)表示abc,(abc|def)表示abc、def
\d 數字,等價于[0-9]
\D 比對非數字
\w 比對非特殊字元,即a-z、A-Z、0-9、_、漢字
\W 比對特殊字元,即非字母、非數字、非漢字、非_
\n 比對一個換行符
\s 比對空白
\S 比對非空白

正規表達式文法執行個體:

正規表達式 對應字元串
p(Y|YT|YTH|YTHO)?N ‘PN’,‘PYN’,‘PYTN’,‘PYTHN’,‘PYTHON’
PYTHON+ ‘PYTHON’,‘PYTHONN’,‘PYTHONNN’ …
PY[TH]ON ‘PYTON’,‘PYHON’
PY[^TH]?ON ‘PYON’,‘PYaON’,‘PYbON’,‘PYcON’ …
PY{ : 3}N ‘PN’,‘PYN’,‘PYYN’、‘PYYYN’

經典正規表達式執行個體:

正規表達式 對應字元串

^[A-Za-z]+$

由26個字母組成的字元串

^[A-Za-z0-9]+$

由26個字母和數字組成的字元串

^\d+$

整數形式的字元串

^[0-9]*[1-9][0-9]*$

正整數形式的字元串

[1-9]\d{5}

中國境内的郵政編碼,6位

[\u4e00-\u9fa5]

比對中文字元

\d{3}-\d{8}|\d{4}-\d{7}

國内電話号碼,010-68913536

\d+.\d+.\d+.\d+. 或 \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}

比對IP位址的字元串

其實正規表達式不是Python僅有的,它也出現在其他的程式設計語言中,隻不過文法可能有一點不同。Python中的re庫提供了整個正規表達式的實作,下面就來介紹re庫。

2.3.2 Re庫

2.3.2.1 Re庫的介紹

Re庫是Python的标準庫,主要用于字元串比對。

re文檔

python中的re庫文檔

2.3.2.2 Re庫的使用

要使用Re庫,必須先安裝re庫:

pip install re

re庫的主要功能函數:

函數 說明
re.match() 從一個字元串的開始位置起比對正規表達式
re.search() 在一個字元串中搜尋比對正規表達式的第一個位置
re.findall() 搜尋字元串,以清單類型傳回全部能比對的字元串
re.sub() 在一個字元串中替換所有比對正規表達式的子串,傳回替換後的字元串
2.3.2.2.1 re.match()方法
re.match(pattern, string, flags=0)
  • pattern:正規表達式(可以是字元串或原生字元串)
  • string:待比對字元串
  • flags:正規表達式使用時的控制标記(可選)
​ 常見的控制标記:
常用标記 說明
re.I re.IGNORECASE 忽略正規表達式的大小寫,[A-Z]能夠比對小寫字元
re.M re.MULTILTNE 正規表達式中的^操作符能夠将給定字元串的每一行當做比對開始
re.S re.DOTALL 正規表達式中的.操作符能夠比對所有的字元,預設比對除換行符以外的所有字元

match()方法會嘗試從字元串的起始位置比對正規表達式,如果比對,就傳回比對成功的結果,否則,傳回None:

import re

# 2.29 re.match()方法的使用
content = 'dfs 234 d 3 34'
result = re.match('..', content)
print(type(result))
print(result)
print(result.group())
print(result.span())
           

下面是執行結果:

<class 're.Match'>
<re.Match object; span=(0, 2), match='df'>
df
(0, 2)
           

從結果可以看出,re.match()方法傳回一個re.Match對象,該對象有兩種常用的方法:

  • group():比對結果的内容,如果有分組,則分組是從1開始的,group[1]表示第一個分組,group[2]表示第二個分組,以此類推。
  • span():輸出比對到的字元串在原字元串中的起始位置,上面的(0,2)中的0和2就代表了df在’dfs 234 d 3 34’中的起始位置。

正規表達式…比對到的字元串是df。

2.3.2.2.2 使用分組

上面的例子中,我們用match()方法比對到了我們想要的字元串,但是,如果我們想要的字元串在比對結果中該怎麼辦?

例如:

# 2.30 使用分組()
import re

content = 'a1234567atsea'
result = re.match('a\d{7}a', content)
print(result)
print(result.group())
print(result.span())
           

我們要在content中将數字提取出來,我們發現數字都包含在a這個字母中間,是以用

a\\d{7}a

這個正規表達式來提取,\d表示任意一個數字,再用{7}将\d(任意一個數字)比對7個,運作結果如下:

a1234567a
(0, 9)
           

我麼發現比對結果中開頭和結尾都包含了一個a,如何隻得到1234567能,我們隻需要使用分組,并将上面的代碼修改一下就行了:

import re

# 2.31 分組()的使用
content = 'a1234567atsea'
result = re.match('a(\d{7})a', content)
print(result.group())
print(result.span())
print(result.group(1))
           

運作結果如下:

a1234567a
(0, 9)
1234567
           

将正規表達式中的\d{7}的兩邊加上小括号,将其作為一個分組,在比對結果中使用group(1)将分組取出,可以看到,我們想要的1234567就在比對結果中的第一個分組中了(group(1))。

2.3.2.2.3 通用比對和比對操作符

在使用正規表達式的時候,要熟練使用.*(通用比對),其中,.可以比對任意一個字元,*(星)代表比對前面的字元無限次,是以它們組合在一起就可以比對任意字元了(換行符除外)。

下面來看一個通用比對(.*)的例子:

import re

# 2.32 通用比對(.*)的使用
content = 'rtgfga1234567atsea'
result = re.match('.*(\d{7}).*', content)
print(result.group())
print(result.span())
print(result.group(1))
           

運作結果如下:

rtgfga1234567atsea
(0, 18)
1234567
           

上面的例子中,我們使用了.*來比對數字前的任意字元串和數字之後的任意字元串,在使用分組獲得 我們想要的數字。

有時候,我們要比對的字元中包括操作符該怎麼辦?可以使用\來将操作符轉義,請看下面的例子:

import re

# 2.33 在正規表達式中使用轉義符
content = '12df www.baidu.com df'
result = re.match('12df\s(www\.baidu\.com)\sdf', content)
print(result.group())
print(result.span())
print(result.group(1))
           

在content中,我們要提取www.baidu.com,其中的.是操作符,在寫正規表達式時,我們不能用.來比對. 因為.代表任意一個字元,我們用\來将其轉義,就可以用\.來比對點了。運作結果如下:

12df www.baidu.com df
(0, 21)
www.baidu.com
           
2.3.2.2.4 貪婪與非貪婪

由于.*代表任意字元串,這就有一個問題,例如:

import re

# 2.34 貪婪模式
content = 'dfadas1234567assedf'
result = re.match('df.*(\d+).*df', content)
print(result.group())
print(result.span())
print(result.group(1))
           

運作結果如下:

dfadas1234567assedf
(0, 19)
7
           

(\d+)分組隻比對到了7這一個數字,我們想要比對1234567,這是為什麼?

這就涉及到了貪婪與非貪婪,由于.*可以比對任意長度的字元串,是以.*就盡可能的的比對較多的字元,于是,它就比對了adas123456,而隻讓\d+隻比對到一個7。

貪婪:讓.*比對盡可能多的字元

非貪婪:讓.*比對盡可能少的字元

預設.*是貪婪的,要讓.*是非貪婪的,隻需要在.*的後面加上?,即:.*?

知道如何将.*設定為非貪婪模式後,我們就可以将上面的代碼改為如下的代碼:

import re

# 2.35 非貪婪模式
content = 'dfadas1234567assedf'
result = re.match('df.*?(\d+).*?df', content)
print(result.group())
print(result.span())
print(result.group(1))

           

運作結果如下:

dfadas1234567assedf
(0, 19)
1234567
           

這就比對到了我們想要的1234567了。

2.3.2.2.5 控制标記

正規表達式可以包含一些可選标志修飾符來控制比對的模式,常見的控制标記大家可以看上面介紹re.match()方法中列出的控制标記表格。

下面的代碼中,我們任然是提取字元串中的所有數字:

import re

content = 'dfadas1234567assedf'
result = re.match('^df.*?(\d+).*?df$', content)
print(result.group())
print(result.span())
print(result.group(1))
           

運作結果如下:

dfadas1234567assedf
(0, 19)
1234567
           

我們成功将字元串中的所有數字提取出來了,但是,我将content修改一下:

import re

content = '''dfadas1234567ass
          edf'''
result = re.match('^df.*?(\d+).*?df$', content)
print(result.group())
print(result.span())
print(result.group(1))
           

再運作:

Traceback (most recent call last):
  File "E:/pycharmWorkStation/venv/Include/draft/test.py", line 6, in <module>
    print(result.group())
AttributeError: 'NoneType' object has no attribute 'group'

Process finished with exit code 1
           

發現出錯了!原因是.比對任意一個除了換行符之外的任意字元,是以.*?比對到換行符就不能比對了,導緻我們沒有比對到任何字元,放回結果為None,而在第6行,我們調用了None的group()方法。

要修正這個錯誤,我們隻需要添加一個re.S控制标記,這個标記的作用是使.比對任意一個包括換行符在内的字元。

import re

# 2.36 控制标記的使用
content = '''dfadas1234567ass
          edf'''
result = re.match('^df.*?(\d+).*?df$', content, re.S)
print(result.group())
print(result.span())
print(result.group(1))
           

運作結果如下:

dfadas1234567ass
          edf
(0, 30)
1234567
           

這個re.S控制标記在網頁比對中經常用到。因為HTMl節點經常會換行,加上它,就可以比對節點與節點中的換行了。

2.3.2.2.6 re.search()

上面講的match()方法是從字元串的開頭開始比對的,一旦開頭就不能比對,就會導緻比對的失敗,請看下面的例子:

import re

# 2.37 re.match()方法是從頭開始比對的
content = 'df colle 123'
result = re.match('colle\s123', content)
print(result.group())
print(result.span())
           

運作結果出錯,沒有比對到結果,傳回的是None,None對象沒有group()方法。

re.search():在比對時掃描整個字元串,讓後傳回成功比對的第一個結果,如果搜尋完了還未找到比對的,就傳回None。也就是說,正規表達式可以是字元串的一部分
import re

# 2.38 re.search()方法的使用
content = 'df colle 123'
result = re.search('colle\s123', content)
print(result.group())
print(result.span())
           

運作結果:

colle 123
(3, 12)
           
2.3.2.2.7 re.findall()

上面所講到的search()方法可以傳回比對到的第一個内容,如果我們想要得到所有比對到的結果就可以使用findall()方法。

re.findall():搜尋字元串,以清單類型傳回全部能比對的子串
import re

# 2.39 re.findall()方法的使用
content = 'df colle 123 colle 123'
result = re.findall('colle\s123', content)
print(result)
           

運作結果:

2.3.2.2.8 re.sub()
re.sub():将文本中是以比對的内容替換為指定的文本
import re

# 2.40 re.sub()方法的使用
content = 'dfcolle123colle123'
content = re.sub('\d', '', content)
print(content)
           

運作結果:

dfcollecolle
           

上面的代碼中,我們将content中所有與\d(任意一個數字)比對的結果替換為’ ',就去掉了content中所有的數字。

2.3.2.2.9 re.compile()
re.compile():将正則字元串編譯成正規表達式對象,可以用來複用。
import re

# 2.41 re.compile()方法的使用
content1 = 'dfcolle123colle123'
content2 = 'sdf123e'
content3 = 'ss23dsfd'

pattern = re.compile('\d')

content1 = re.sub(pattern, '', content1)
content2 = re.sub(pattern, '', content2)
content3 = re.sub(pattern, '', content3)
print(content1,' ',content2,' ',content3)
           

代碼中,我們将’\d‘編譯為一個正規表達式對象,并在下面的代碼中将它複用。

運作結果:

dfcollecolle   sdfe   ssdsfd
           

2.3.3 使用Re來爬取tx視訊

下面來使用re來擷取tx視訊首頁中的所有連結和排行榜中所有的電影名稱。

打開tx視訊的首頁,右擊,“檢查”,選擇“元素”:

Python爬蟲基本庫的使用第二章 基本庫的使用

随便找到一個連結,例如我在圖中畫出來的,根據它寫出比對所有連接配接的正規表達式:

'"((https|http)://.*?)"'

按照如下的圖示來擷取請求的URL、user-Agent、cookie

Python爬蟲基本庫的使用第二章 基本庫的使用
Python爬蟲基本庫的使用第二章 基本庫的使用

重新回到“元素”:

按照如下操作擷取排行榜中電影所在的元素:

Python爬蟲基本庫的使用第二章 基本庫的使用

重複上面的操作,多擷取幾個排行榜中電影名所在的元素:

例如:

<span class="rank_title">有翡</span>
<span class="rank_title">我的小确幸</span>
<span class="rank_title">我就是這般女子</span>
           

根據它寫出提取排行榜電影名稱的正規表達式為:

‘<span\sclass=“rank_title”>(.*?)’

根據上面步驟得出的資訊可以寫出如下代碼:

import re
import requests

# 2.42 使用re爬取騰訊視訊的小例子
url = "https://v.qq.com/"   # 要爬取的連結
headers = {  # 構造請求頭
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'\
                  ' AppleWebKit/537.36 (KHTML, like Gecko) C'\
                  'hrome/88.0.4324.96 Safari/537.36 Edg/88.0.'\
                  '705.53',
    'cookie': 'pgv_pvi=2265568256; pgv_pvid=1230518102; tvfe'\
              '_boss_uuid=19b8c4da4cc7e833; ts_uid=9797476283'\
              '; ts_refer=www.baidu.com/link; RK=VGQx4w/ntj; '\
              'ptcz=fe2dbdf4d8d7efb795bfdc0deaa0429286aa73e0dd'\
              '444a9173fe43fc7b145a1e; ptag=www_baidu_com; ad_pl'\
              'ay_index=77; pgv_info=ssid=s5748488123; ts_last=v.'\
              'qq.com/; bucket_id=9231006; video_guid=8b478b9f33d3db'\
              '89; video_platform=2; qv_als=cyHwW4MZHa8e9NWRA1161181'\
              '1694iJW+zw==',
}
proxy={  # 代理
    "HTTP": "113.3.152.88:8118",
    "HTTPS":"219.234.5.128:3128",
}

r = requests.get(url=url, headers=headers, proxies=proxy, timeout=3)  # 傳入url、headers、proxies、timeout構造get請求
print("狀态碼為:", r.status_code)   # 列印狀态碼
r.encoding = r.apparent_encoding    # 将編碼方式設定為備用編碼方式

pattern = re.compile('"((https|http)://.*?)"', re.S)   # 使用re來擷取所有的連結,并列印前5個
links = re.findall(pattern, r.text)
print("連結個數為:", len(links))
for i in range(5):
    print(links[i][0])

pattern1 = re.compile('<span\sclass="rank_title">(.*?)</span>', re.S)   # 使用re來擷取排行榜中所有的電影名稱并
movies = re.findall(pattern1, r.text)

print()   # 将排行榜中的所有電影名稱列印出來
for i in movies:
    print(i)
           

當然,這是我的代碼,大家可以将其中的cookie、user-agent和proxy替換為自己的。

運作結果如下:

狀态碼為: 200
連結個數為: 1331
http://m.v.qq.com/index.html?ptag=
https://puui.qpic.cn/vupload/0/common_logo_square.png/0
http://www.w3.org/2000/svg
https://v.qq.com/
https://film.qq.com/

有翡
我的小确幸
我就是這般女子
暗戀橘生淮南
這個世界不看臉
山海情[原聲版]
陀槍師姐2021[國語版]
黑白禁區
大秦賦
陳情令
長安伏妖
詭婳狐
除暴
赤狐書生
有匪·破雪斬
蜘蛛俠:平行宇宙
重案行動之搗毒任務
武動乾坤:九重符塔
昆侖神宮
絕對忠誠之國家利益
哈哈哈哈哈
王牌對王牌 第6季
歡樂喜劇人 第7季
我就是演員 第3季
平行時空遇見你
現在就告白 第4季
你好生活 第2季
非常完美
乘風破浪的姐姐slay全場
天賜的聲音 第2季
鬥羅大陸
開心錘錘
狐妖小紅娘
雪鷹領主
武神主宰
靈劍尊
豬屁登
萬界仙蹤
           

當然,這是我的運作結果,大家的運作結果可能和我不一樣,因為排行榜是會變化的。

繼續閱讀