最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python進階多線程爬取網(wǎng)頁項目實戰(zhàn)

 更新時間:2021年10月21日 15:44:43   作者:Python進階多線程爬取網(wǎng)頁項目實戰(zhàn)  
這篇文章主要為大家介紹了Python進階,Python多線程爬取網(wǎng)頁項目實戰(zhàn)的示例呈現(xiàn)步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助

上一篇文章介紹了并發(fā)和多線程的概念,這次就來向大家上一個實戰(zhàn)來講解一下如何真正的運用上多線程這個概念。
有需要的可以看看我之前這篇文章:Python進階篇之多線程爬取網(wǎng)頁

一、網(wǎng)頁分析

這次我們選擇爬取的網(wǎng)站是水木社區(qū)的Python頁面
網(wǎng)頁:https://www.mysmth.net/nForum/#!board/Python?p=1

在這里插入圖片描述

根據(jù)慣例,我們第一步還是分析一下頁面結(jié)構(gòu)和翻頁時的請求。

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

通過前三頁的鏈接分析后得知,每一頁鏈接中最后的參數(shù)是頁數(shù),我們修改它即可得到其他頁面的數(shù)據(jù)。

再來分析一下,我們需要獲取帖子的鏈接就在id 為 body 的 section下,然后一層一層找到里面的 table,我們就能遍歷這些鏈接的標(biāo)題。

在這里插入圖片描述

我們點開一篇帖子:https://www.mysmth.net/nForum/#!article/Python/162717

和前面一樣,我們先分析標(biāo)題和內(nèi)容在網(wǎng)頁中的結(jié)構(gòu)

不難發(fā)現(xiàn),主題部分只要找到 id 為 main 的 section 下面的 class 為 b-head corner 的下面第二個 span即可
主題部分

在這里插入圖片描述

而內(nèi)容部分只要找到class 為 a-wrap corner 的 div,找到下面的 a-content即可。
內(nèi)容部分

在這里插入圖片描述

分析網(wǎng)頁結(jié)構(gòu)后,我們就可以開始寫代碼了!

二、代碼實現(xiàn)

首先要確定要保存什么內(nèi)容:這次我們保存水木社區(qū) Python 版面前 10 頁的所有帖子標(biāo)題和帖子第一頁的所有回復(fù)。

解析列表頁,得到所有的帖子鏈接

from bs4 import BeautifulSoup
# 解析列表頁內(nèi)容,得到這一頁的內(nèi)容鏈接
def parse_list_page(text):
  soup = BeautifulSoup(text, 'html.parser')
	# 下面相當(dāng)于 soup.find('table', class_='board-list tiz').find('tbody')
  tbody = soup.find('table', class_='board-list tiz').tbody
  urls = []
  for tr in tbody:
    td = tr.find('td', class_='title_9')
    urls.append(td.a.attrs['href'])
  return urls

解析內(nèi)容頁,得到標(biāo)題和這一頁的所有帖子內(nèi)容

# 解析內(nèi)容頁,得到標(biāo)題和所有帖子內(nèi)容
def parse_content_page(text):
  soup = BeautifulSoup(text, 'html.parser')
  title = soup.find('span', class_='n-left').text.strip('文章主題:').strip()
  content_div = soup.find('div', class_='b-content corner')
  contents = []
  for awrap in content_div.find_all('div', class_='a-wrap corner'):
    content = awrap.p.text
    contents.append(content)
  return title, contents

把列表頁的鏈接轉(zhuǎn)換成我們要抓取的鏈接

def convert_content_url(path):
  URL_PREFIX = 'http://www.mysmth.net'
  path += '?ajax'
  return URL_PREFIX + path

生成前 10 頁的列表頁鏈接

list_urls = []
for i in range(1, 11):
  url = 'http://www.mysmth.net/nForum/board/Python?ajax&p='
  url += str(i)
  list_urls.append(url)

下面是得到前 10 頁列表頁里所有正文的鏈接。這個時候我們使用線程池的方式來運行

import requests
from concurrent import futures
session = requests.Session()
executor = futures.ThreadPoolExecutor(max_workers=5)
# 這個函數(shù)獲取列表頁數(shù)據(jù),解析出鏈接,并轉(zhuǎn)換成真實鏈接
def get_content_urls(list_url):
  res = session.get(list_url)
  content_urls = parse_list_page(res.text)
  real_content_urls = []
  for url in content_urls:
    url = convert_content_url(url)
    real_content_urls.append(url)
  return real_content_urls
# 根據(jù)剛剛生成的十個列表頁鏈接,開始提交任務(wù)
fs = []
for list_url in list_urls:
  fs.append(executor.submit(get_content_urls, list_url))
futures.wait(fs)
content_urls = set()
for f in fs:
  for url in f.result():
    content_urls.add(url)

在這里要注意一下,第 23 行中我們使用了 set() 函數(shù),作用是去除重復(fù)值。它的原理是創(chuàng)建一個 Set(集合),集合 是 Python 中的一種特殊數(shù)據(jù)類型,其中可以包含多個元素,但是不能重復(fù)。我們來看看 set() 的用法

numbers = [1, 1, 2, 2, 2, 3, 4]
unique = set(numbers)
print(type(unique))
# 輸出:<class 'set'>
print(unique)
# 輸出:{1, 2, 3, 4}

我們看到,set() 將列表 numbers 轉(zhuǎn)換成了沒有重復(fù)元素的集合 {1, 2, 3, 4}。

我們利用這個特性,首先在 23 行通過 content_urls = set() 創(chuàng)建了一個空集合,之后在其中添加鏈接時,就會自動去除多次出現(xiàn)的鏈接。

得到了所有正文鏈接之后,我們解析正文頁內(nèi)容,放到一個字典里

# 獲取正文頁內(nèi)容,解析出標(biāo)題和帖子
def get_content(url):
  r = session.get(url)
  title, contents = parse_content_page(r.text)
  return title, contents
# 提交解析正文的任務(wù)
fs = []
for url in content_urls:
  fs.append(executor.submit(get_content, url))
futures.wait(fs)
results = {}
for f in fs:
  title, contents = f.result()
  results[title] = contents
print(results.keys())

就這樣,我們完成了多線程的水木社區(qū)爬蟲。打印 results.keys() 可以看到所有帖子的標(biāo)題。

這次爬取了前十頁的所有主題,以及他們的第一頁回復(fù)。一共 10 個列表頁、300 個主題頁,解析出 1533 條回復(fù)。在一臺網(wǎng)絡(luò)良好、性能普通的機器上測試執(zhí)行只花費了 13 秒左右。

完整代碼如下

import requests
from concurrent import futures
from bs4 import BeautifulSoup
# 解析列表頁內(nèi)容,得到這一頁的內(nèi)容鏈接
def parse_list_page(text):
  soup = BeautifulSoup(text, 'html.parser')
  tbody = soup.find('table', class_='board-list tiz').tbody
  urls = []
  for tr in tbody:
    td = tr.find('td', class_='title_9')
    urls.append(td.a.attrs['href'])
  return urls
# 解析內(nèi)容頁,得到標(biāo)題和所有帖子內(nèi)容
def parse_content_page(text):
  soup = BeautifulSoup(text, 'html.parser')
  title = soup.find('span', class_='n-left').text.strip('文章主題:').strip()
  content_div = soup.find('div', class_='b-content corner')
  contents = []
  for awrap in content_div.find_all('div', class_='a-wrap corner'):
    content = awrap.p.text
    contents.append(content)
  return title, contents
# 把列表頁得到的鏈接轉(zhuǎn)換成我們要抓取的鏈接
def convert_content_url(path):
  URL_PREFIX = 'http://www.mysmth.net'
  path += '?ajax'
  return URL_PREFIX + path
# 生成前十頁的鏈接
list_urls = []
for i in range(1, 11):
  url = 'http://www.mysmth.net/nForum/board/Python?ajax&p='
  url += str(i)
  list_urls.append(url)
session = requests.Session()
executor = futures.ThreadPoolExecutor(max_workers=5)
# 這個函數(shù)獲取列表頁數(shù)據(jù),解析出鏈接,并轉(zhuǎn)換成真實鏈接
def get_content_urls(list_url):
  res = session.get(list_url)
  content_urls = parse_list_page(res.text)
  real_content_urls = []
  for url in content_urls:
    url = convert_content_url(url)
    real_content_urls.append(url)
  return real_content_urls
# 根據(jù)剛剛生成的十個列表頁鏈接,開始提交任務(wù)
fs = []
for list_url in list_urls:
  fs.append(executor.submit(get_content_urls, list_url))
futures.wait(fs)
content_urls = set()
for f in fs:
  for url in f.result():
    content_urls.add(url)
# 獲取正文頁內(nèi)容,解析出標(biāo)題和帖子
def get_content(url):
  r = session.get(url)
  title, contents = parse_content_page(r.text)
  return title, contents
# 提交解析正文的任務(wù)
fs = []
for url in content_urls:
  fs.append(executor.submit(get_content, url))
futures.wait(fs)
results = {}
for f in fs:
  title, contents = f.result()
  results[title] = contents
print(results.keys())

本次分享到此結(jié)束,謝謝大家閱讀?。?br /> 有問題歡迎評論區(qū)留言?。?/p>

更多關(guān)于Python多線程爬取網(wǎng)頁實戰(zhàn)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Tensorflow進行多維矩陣的拆分與拼接實例

    Tensorflow進行多維矩陣的拆分與拼接實例

    今天小編就為大家分享一篇Tensorflow進行多維矩陣的拆分與拼接實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-02-02
  • 原來我一直安裝 Python 庫的姿勢都不對呀

    原來我一直安裝 Python 庫的姿勢都不對呀

    平常我都是直接執(zhí)行 pip install 安裝的第三方庫,很多教程也是這么介紹的,一直以來我都認為這是標(biāo)準(zhǔn)的、正確的安裝 Python 第三方庫的姿勢。下面小編給大家分享一篇教程,一起看看吧
    2019-11-11
  • Python pip安裝第三方庫實現(xiàn)過程解析

    Python pip安裝第三方庫實現(xiàn)過程解析

    這篇文章主要介紹了Python pip安裝第三方庫實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • python入門之井字棋小游戲

    python入門之井字棋小游戲

    這篇文章主要為大家詳細介紹了python入門學(xué)習(xí)之井字棋小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • Django?報錯:Broken?pipe?from?('127.0.0.1',?58924)的解決

    Django?報錯:Broken?pipe?from?('127.0.0.1',?5892

    這篇文章主要介紹了Django?報錯:Broken?pipe?from?('127.0.0.1',?58924)的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Python+PyQt5編寫圖片格式轉(zhuǎn)換器

    Python+PyQt5編寫圖片格式轉(zhuǎn)換器

    這篇文章主要為大家詳細介紹了如何利用Python和PyQt5編寫一個簡單的圖片格式轉(zhuǎn)換器,文中的示例代碼講解詳細,感興趣的小伙伴可以動手嘗試一下
    2023-07-07
  • Python retrying 重試機制的使用方法

    Python retrying 重試機制的使用方法

    我們在程序開發(fā)中,經(jīng)常會需要請求一些外部的接口資源,而且我們不能保證每次請求一定會成功,所以這些涉及到網(wǎng)絡(luò)請求的代碼片段就需要加上重試機制。本文就來詳細的介紹一下,感興趣的可以了解一下
    2021-09-09
  • python中的函數(shù)遞歸和迭代原理解析

    python中的函數(shù)遞歸和迭代原理解析

    這篇文章主要介紹了python中的函數(shù)遞歸和迭代原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • python中實現(xiàn)詞云圖的示例

    python中實現(xiàn)詞云圖的示例

    這篇文章主要介紹了python中實現(xiàn)詞云圖的示例,幫助大家更好的理解和使用python,感興趣的朋友可以了解下
    2020-12-12
  • python模擬點擊在ios中實現(xiàn)的實例講解

    python模擬點擊在ios中實現(xiàn)的實例講解

    在本篇文章里小編給大家整理的是一篇關(guān)于python模擬點擊在ios中實現(xiàn)的實例講解內(nèi)容,有需要的朋友們可以參考下。
    2020-11-11

最新評論

望城县| 揭东县| 当雄县| 盐池县| 方正县| 兴国县| 衡东县| 东乌| 同仁县| 探索| 章丘市| 和平县| 越西县| 德江县| 仁布县| 阿鲁科尔沁旗| 东乌珠穆沁旗| 兴安县| 东宁县| 明溪县| 伊川县| 横山县| 会昌县| 来宾市| 郸城县| 元江| 建阳市| 固镇县| 娱乐| 调兵山市| 长岭县| 鹿邑县| 乌鲁木齐县| 卫辉市| 望奎县| 宜君县| 平和县| 青浦区| 来宾市| 巨野县| 长寿区|