寫在前面
為了不浪費大家時間,首先聲明兩點:
- 在第一篇文章:簡單網站爬蟲的所有技能(requests+bs4)涉及到的技能,不會重復講解
- 這篇文章不會涉及任何正則表達式基礎內容,只會有新鮮的實戰部分,自學正則表達式基礎內容,或者看看Python-正則表達式-re模塊
- 比如\d表示數字
- * 表示重復0或多次
- ......
- 對,只用了解概念就行了,所以不要太緊張
建議爬蟲初學者做完簡單網站爬蟲的所有技能(requests+bs4)思考題。
- 如無必要,勿增實體
- 用正確的工具,做正確的事情
正則表達式是你掌握簡單網站爬蟲之后的進階技能,如果requests+bs4就可以滿足需求,為什么自己要平添煩惱。
為什么要用正則
因為遇到了棘手的問題,不然誰會去學這么難懂的正則表達式
今天爬取的網址是:為知筆記吧首頁,爬取的內容是回復數
STOP!別點上面的文字,點擊文字的時候,用簡單網站爬蟲的所有技能(requests+bs4)提到的檢查元素工具看看文字背后的真實url,這是一個非常好的上網習慣。檢查了之后,接着往下看。
(注:與為知筆記無任何利益相關)
找到回復數
(動態圖只默認播放一次,嗯,我錄制的時候點錯了一個選項。但是解決也很簡單,比如
PC:在圖片上右鍵,點擊”在新標簽頁中打開圖片“
APP:點一下圖片)
爬取網頁源代碼
看看網頁源代碼是不是真的包含了我們要的內容—回復數
# -*- coding: utf-8 -*-
__author__ = 'duohappy'
import requests
from bs4 import BeautifulSoup
headers = {"User-Agent": 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36'}
url = "http://tieba.baidu.com/f?kw=%E4%B8%BA%E7%9F%A5%E7%AC%94%E8%AE%B0"
web_data = requests.get(url, headers=headers)
# 新知識點 web_data.content
# 以字節的方式訪問web_data,所以用'wb'模式寫入
with open('tieba_text.txt', 'wb') as f:
f.write(web_data.content)
搬出BeautifulSoup
網頁源代碼里包含了回復數,那么我們來用css selector語法把內容提取出來吧。稍等,看看soup里有沒有
# -*- coding: utf-8 -*-
__author__ = 'duohappy'
import requests
from bs4 import BeautifulSoup
headers = {"User-Agent": 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36'}
url = "http://tieba.baidu.com/f?kw=%E4%B8%BA%E7%9F%A5%E7%AC%94%E8%AE%B0"
web_data = requests.get(url, headers=headers)
web_data.encoding = 'utf-8'
web_text = web_data.text
soup = BeautifulSoup(web_text, 'lxml')
with open('soup_text.txt', 'w') as f:
f.write(str(soup)) # soup對象轉成字符串
到此,我們要學正則表達式了!用正確的工具,做正確的事
收集建議
# -*- coding: utf-8 -*-
__author__ = 'duohappy'
import re
import requests
from bs4 import BeautifulSoup
headers = {"User-Agent": 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36'}
url = "http://tieba.baidu.com/f?kw=%E4%B8%BA%E7%9F%A5%E7%AC%94%E8%AE%B0"
web_data = requests.get(url, headers=headers)
web_data.encoding = 'utf-8'
web_text = web_data.text
reply_nums = re.findall(r'(?<="回復">)[\s\S]*?(?=</span>)', web_text)
print(reply_nums)
正則表達式的心法
文章不涉及招式的講解,需要自學正則表達式基礎內容如零寬斷言、懶惰模式、貪婪模式等
First Time
最容易理解的一個想法,也就是re.search()的用法: 掃描整個字符串並返回第一個成功的匹配
爬取帖子的創建時間,觀察網頁結構,寫出匹配時間的正則
# -*- coding: utf-8 -*-
__author__ = 'duohappy'
import re
import requests
headers = {"User-Agent": 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36'}
url = "https://tieba.baidu.com/p/5054019406"
web_data = requests.get(url, headers=headers)
web_data.encoding = 'utf-8'
source_code = web_data.text
## 匹配時間的正則
time_pattern = r'\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}'
# 匹配第一個時間
create_time = re.search(time_pattern, source_code).group()
print(create_time)
Focus
反復聚焦
匹配帖子創建者的用戶名,可以先想一想怎么匹配,再讀源代碼
如果你對網頁結構敏感性越高,那么寫出的正則適用性越大,通過檢查元素,發現用戶名存在於一段html代碼中,這段代碼有一個class,class="d_name",d_name有什么含義?嘿嘿嘿
<li class="d_name" data-field="{"user_id":1081331744}">
<a data-field="{"un":"suoai1335"}" alog-group="p_author" class="p_author_name j_user_card" href="/home/main?un=suoai1335&ie=utf-8&fr=pb" target="_blank">suoai1335</a>
</li>
# -*- coding: utf-8 -*-
__author__ = 'duohappy'
import re
import requests
headers = {"User-Agent": 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36'}
url = "https://tieba.baidu.com/p/5054019406"
web_data = requests.get(url, headers=headers)
web_data.encoding = 'utf-8'
source_code = web_data.text
# 匹配包含用戶名正則表達式
include_username_pattern = r'(?<=<li class="d_name"\sdata)[\s\S]*?(?=</a>)'
# 匹配出來包含用戶名的html代碼
include_username = re.search(include_username_pattern, source_code).group()
# 匹配用戶名的正則表達式
username_pattern = r'(?<=target="_blank">)[\s\S]*'
# First Time
username = re.search(username_pattern, include_username).group()
print(username)
下面用動畫來演示一下,一般我們容易掉進一個誤區里,認為要匹配什么,就只寫匹配內容的正則表達式,可是呢?這個正則表達式又很難寫,寫完了又不是很通用,這個時候可以考慮換一種思路,發散一下思維,寫一個正則表達式來匹配更多的內容,然后針對這一內容,再寫一個正則表達式,最終取得自己想要的內容。
參考資料
感謝閱讀,看張圖片輕松一下
**
動手,你才能學會編程
分享,你才能學得透徹
**