亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

以視頻爬取實(shí)例講解Python爬蟲神器Beautiful Soup用法

 更新時(shí)間:2016年01月20日 10:45:31   作者:Jark  
這篇文章主要以視頻爬取實(shí)例來講解Python爬蟲神器Beautiful Soup的用法,Beautiful Soup是一個(gè)為Python獲取數(shù)據(jù)而設(shè)計(jì)的包,簡(jiǎn)潔而強(qiáng)大,需要的朋友可以參考下

1.安裝BeautifulSoup4
easy_install安裝方式,easy_install需要提前安裝

easy_install beautifulsoup4

pip安裝方式,pip也需要提前安裝.此外PyPi中還有一個(gè)名字是 BeautifulSoup 的包,那是 Beautiful Soup3 的發(fā)布版本.在這里不建議安裝.

pip install beautifulsoup4

Debain或ubuntu安裝方式

apt-get install Python-bs4

你也可以通過源碼安裝,下載BS4源碼

Python setup.py install

2.小試牛刀

# coding=utf-8
'''
@通過BeautifulSoup下載百度貼吧圖片
'''
import urllib
from bs4 import BeautifulSoup
url = 'http://tieba.baidu.com/p/3537654215'

# 下載網(wǎng)頁
html = urllib.urlopen(url)
content = html.read()
html.close()

# 使用BeautifulSoup匹配圖片
html_soup = BeautifulSoup(content)
# 圖片代碼我們?cè)赱Python爬蟲基礎(chǔ)1--urllib]( http://blog.xiaolud.com/2015/01/22/spider-1st/ "Python爬蟲基礎(chǔ)1--urllib")里面已經(jīng)分析過了
# 相較通過正則表達(dá)式去匹配,BeautifulSoup提供了一個(gè)更簡(jiǎn)單靈活的方式
all_img_links = html_soup.findAll('img', class_='BDE_Image')

# 接下來就是老生常談的下載圖片
img_counter = 1
for img_link in all_img_links:
  img_name = '%s.jpg' % img_counter
  urllib.urlretrieve(img_link['src'], img_name)
  img_counter += 1

很簡(jiǎn)單,代碼注釋里面已經(jīng)解釋的很清楚了.BeautifulSoup提供了一個(gè)更簡(jiǎn)單靈活的方式,去分析網(wǎng)站源碼,更快獲取圖片link.


3.爬取實(shí)例
3.1基本的抓取技術(shù)
在寫一個(gè)爬蟲腳本時(shí),第一件事情就是手動(dòng)觀察要抓取的頁面來確定數(shù)據(jù)如何定位。

首先,我們要看一看在 http://pyvideo.org/category/50/pycon-us-2014 上的 PyCon 大會(huì)視頻列表。檢查這個(gè)頁面的 HTML 源代碼我們發(fā)現(xiàn)視頻列表的結(jié)果差不多是長(zhǎng)這樣的:

<div id="video-summary-content">
  <div class="video-summary">  <!-- first video -->
    <div class="thumbnail-data">...</div>
    <div class="video-summary-data">
      <div>
        <strong><a href="#link to video page#">#title#</a></strong>
      </div>
    </div>
  </div>
  <div class="video-summary">  <!-- second video -->
    ...
  </div>
  ...
</div>

那么第一個(gè)任務(wù)就是加載這個(gè)頁面,然后抽取每個(gè)單獨(dú)頁面的鏈接,因?yàn)榈?YouTube 視頻的鏈接都在這些單獨(dú)頁面上。

使用requests來加載一個(gè) web 頁面是非常簡(jiǎn)單的:

import requests
response = requests.get('http://pyvideo.org/category/50/pycon-us-2014')

就是它!在這個(gè)函數(shù)返回后就能從response.text中獲得這個(gè)頁面的 HTML 。

下一個(gè)任務(wù)是抽取每一個(gè)單獨(dú)視頻頁面的鏈接。通過 BeautifulSoup 使用 CSS 選擇器語法就能完成它,如果你是客戶端開發(fā)者的話你可能對(duì)這會(huì)很熟悉。

為了獲得這些鏈接,我們要使用一個(gè)選擇器,它能抓取在每一個(gè) id 為video-summary-data的<div>中所有的<a>元素。由于每個(gè)視頻都有幾個(gè)<a>元素,我們將只保留那些 URL 以/video開頭的<a>元素,這些就是唯一的單獨(dú)視頻頁面。實(shí)現(xiàn)上述標(biāo)準(zhǔn)的 CSS 選擇器是div.video-summary-data a[href^=/video]。下面的代碼片段通過 BeautifulSoup 使用這個(gè)選擇器來獲得指向視頻頁面的<a>元素:

import bs4
soup = bs4.BeautifulSoup(response.text)
links = soup.select('div.video-summary-data a[href^=/video]')

因?yàn)槲覀冋嬲P(guān)心的是這個(gè)鏈接本身而不是包含它的<a>元素,我們可以使用列表解析來改善上述代碼。

links = [a.attrs.get('href') for a in soup.select('div.video-summary-data a[href^=/video]')]
現(xiàn)在,我們已經(jīng)有了一個(gè)包含所有鏈接的數(shù)組,這些鏈接指向了每個(gè)單獨(dú)頁面。

下面這段腳本整理了目前我們提到的所有技術(shù):

import requests
import bs4

root_url = 'http://pyvideo.org'
index_url = root_url + '/category/50/pycon-us-2014'

def get_video_page_urls():
  response = requests.get(index_url)
  soup = bs4.BeautifulSoup(response.text)
  return [a.attrs.get('href') for a in soup.select('div.video-summary-data a[href^=/video]')]

print(get_video_page_urls())

如果你運(yùn)行上面這段腳本你將會(huì)獲得一個(gè)滿是 URL 的數(shù)組。現(xiàn)在我們需要去解析每個(gè) URL 以獲得更多關(guān)于每場(chǎng) PyCon 會(huì)議的信息。

3.2抓取相連頁面
下一步是加載我們的 URL 數(shù)組中每一個(gè)頁面。如果你想要看看這些頁面長(zhǎng)什么樣的話,這兒是個(gè)樣例:http://pyvideo.org/video/2668/writing-restful-web-services-with-flask。沒錯(cuò),那就是我,那是我會(huì)議中的一個(gè)!

從這些頁面我們可以抓取到會(huì)議的標(biāo)題,在頁面的頂部能看到它。我們也可以從側(cè)邊欄獲得演講者的姓名和 YouTube 的鏈接,側(cè)邊欄在嵌入視頻的右下方。獲取這些元素的代碼展示在下方:

def get_video_data(video_page_url):
  video_data = {}
  response = requests.get(root_url + video_page_url)
  soup = bs4.BeautifulSoup(response.text)
  video_data['title'] = soup.select('div#videobox h3')[0].get_text()
  video_data['speakers'] = [a.get_text() for a in soup.select('div#sidebar a[href^=/speaker]')]
  video_data['youtube_url'] = soup.select('div#sidebar a[href^=http://www.youtube.com]')[0].get_text()

關(guān)于這個(gè)函數(shù)需要注意的一些事情:

從首頁抓取的 URL 是相對(duì)路徑,所以root_url需要加到前面。
大會(huì)標(biāo)題是從 id 為videobox的<div>里的<h3>元素中獲得的。注意[0]是必須的,因?yàn)檎{(diào)用select()返回的是一個(gè)數(shù)組,即使只有一個(gè)匹配。
演講者的姓名和 YouTube 鏈接的獲取方式與首頁上的鏈接獲取方式類似。
現(xiàn)在就剩下從每個(gè)視頻的 YouTube 頁面抓取觀看數(shù)了。接著上面的函數(shù)寫下去其實(shí)是非常簡(jiǎn)單的。同樣,我們也可以抓取 like 數(shù)和 dislike 數(shù)。

def get_video_data(video_page_url):
  # ...
  response = requests.get(video_data['youtube_url'])
  soup = bs4.BeautifulSoup(response.text)
  video_data['views'] = int(re.sub('[^0-9]', '',
                   soup.select('.watch-view-count')[0].get_text().split()[0]))
  video_data['likes'] = int(re.sub('[^0-9]', '',
                   soup.select('.likes-count')[0].get_text().split()[0]))
  video_data['dislikes'] = int(re.sub('[^0-9]', '', 
                    soup.select('.dislikes-count')[0].get_text().split()[0]))
  return video_data

上述調(diào)用soup.select()函數(shù),使用指定了 id 名字的選擇器,采集到了視頻的統(tǒng)計(jì)數(shù)據(jù)。但是元素的文本需要被處理一下才能變成數(shù)字??紤]觀看數(shù)的例子,在 YouTube 上顯示的是"1,344 views"。用一個(gè)空格分開(split)數(shù)字和文本后,只有第一部分是有用的。由于數(shù)字里有逗號(hào),可以用正則表達(dá)式過濾掉任何不是數(shù)字的字符。

為了完成爬蟲,下面的函數(shù)調(diào)用了之前提到的所有代碼:

def show_video_stats():
  video_page_urls = get_video_page_urls()
  for video_page_url in video_page_urls:
    print get_video_data(video_page_url)

3.3并行處理
上面到目前為止的腳本工作地很好,但是有一百多個(gè)視頻它就要跑個(gè)一會(huì)兒了。事實(shí)上我們沒做什么工作,大部分時(shí)間都浪費(fèi)在了下載頁面上,在這段時(shí)間腳本時(shí)被阻塞的。如果腳本能同時(shí)跑多個(gè)下載任務(wù),可能就會(huì)更高效了,是嗎?

回顧當(dāng)時(shí)寫一篇使用 Node.js 的爬蟲文章的時(shí)候,并發(fā)性是伴隨 JavaScript 的異步特性自帶來的。使用 Python 也能做到,不過需要顯示地指定一下。像這個(gè)例子,我將開啟一個(gè)擁有8個(gè)可并行化進(jìn)程的進(jìn)程池。代碼出人意料的簡(jiǎn)潔:

from multiprocessing import Pool

def show_video_stats(options):
  pool = Pool(8)
  video_page_urls = get_video_page_urls()
  results = pool.map(get_video_data, video_page_urls)

multiprocessing.Pool 類開啟了8個(gè)工作進(jìn)程等待分配任務(wù)運(yùn)行。為什么是8個(gè)?這是我電腦上核數(shù)的兩倍。當(dāng)時(shí)實(shí)驗(yàn)不同大小的進(jìn)程池時(shí),我發(fā)現(xiàn)這是最佳的大小。小于8個(gè)使腳本跑的太慢,多于8個(gè)也不會(huì)讓它更快。

調(diào)用pool.map()類似于調(diào)用常規(guī)的map(),它將會(huì)對(duì)第二個(gè)參數(shù)指定的迭代變量中的每個(gè)元素調(diào)用一次第一個(gè)參數(shù)指定的函數(shù)。最大的不同是,它將發(fā)送這些給進(jìn)程池所擁有的進(jìn)程運(yùn)行,所以在這個(gè)例子中八個(gè)任務(wù)將會(huì)并行運(yùn)行。

節(jié)省下來的時(shí)間是相當(dāng)大的。在我的電腦上,第一個(gè)版本的腳本用了75秒完成,然而進(jìn)程池的版本做了同樣的工作只用了16秒!

3.4完成爬蟲腳本
我最終版本的爬蟲腳本在獲得數(shù)據(jù)后還做了更多的事情。

我添加了一個(gè)--sort命令行參數(shù)去指定一個(gè)排序標(biāo)準(zhǔn),可以指定views,likes或者dislikes。腳本將會(huì)根據(jù)指定屬性對(duì)結(jié)果數(shù)組進(jìn)行遞減排序。另一個(gè)參數(shù),--max代表了要顯示的結(jié)果數(shù)的個(gè)數(shù),萬一你只想看排名靠前的幾條而已。最后,我還添加了一個(gè)--csv選項(xiàng),為了可以輕松地將數(shù)據(jù)導(dǎo)到電子制表軟件中,可以指定數(shù)據(jù)以 CSV 格式打印出來,而不是表對(duì)齊格式。

完整腳本顯示在下方:

import argparse
import re
from multiprocessing import Pool
import requests
import bs4

root_url = 'http://pyvideo.org'
index_url = root_url + '/category/50/pycon-us-2014'

def get_video_page_urls():
  response = requests.get(index_url)
  soup = bs4.BeautifulSoup(response.text)
  return [a.attrs.get('href') for a in soup.select('div.video-summary-data a[href^=/video]')]

def get_video_data(video_page_url):
  video_data = {}
  response = requests.get(root_url + video_page_url)
  soup = bs4.BeautifulSoup(response.text)
  video_data['title'] = soup.select('div#videobox h3')[0].get_text()
  video_data['speakers'] = [a.get_text() for a in soup.select('div#sidebar a[href^=/speaker]')]
  video_data['youtube_url'] = soup.select('div#sidebar a[href^=http://www.youtube.com]')[0].get_text()
  response = requests.get(video_data['youtube_url'])
  soup = bs4.BeautifulSoup(response.text)
  video_data['views'] = int(re.sub('[^0-9]', '',
                   soup.select('.watch-view-count')[0].get_text().split()[0]))
  video_data['likes'] = int(re.sub('[^0-9]', '',
                   soup.select('.likes-count')[0].get_text().split()[0]))
  video_data['dislikes'] = int(re.sub('[^0-9]', '',
                    soup.select('.dislikes-count')[0].get_text().split()[0]))
  return video_data

def parse_args():
  parser = argparse.ArgumentParser(description='Show PyCon 2014 video statistics.')
  parser.add_argument('--sort', metavar='FIELD', choices=['views', 'likes', 'dislikes'],
            default='views',
            help='sort by the specified field. Options are views, likes and dislikes.')
  parser.add_argument('--max', metavar='MAX', type=int, help='show the top MAX entries only.')
  parser.add_argument('--csv', action='store_true', default=False,
            help='output the data in CSV format.')
  parser.add_argument('--workers', type=int, default=8,
            help='number of workers to use, 8 by default.')
  return parser.parse_args()

def show_video_stats(options):
  pool = Pool(options.workers)
  video_page_urls = get_video_page_urls()
  results = sorted(pool.map(get_video_data, video_page_urls), key=lambda video: video[options.sort],
           reverse=True)
  max = options.max
  if max is None or max > len(results):
    max = len(results)
  if options.csv:
    print(u'"title","speakers", "views","likes","dislikes"')
  else:
    print(u'Views +1 -1 Title (Speakers)')
  for i in range(max):
    if options.csv:
      print(u'"{0}","{1}",{2},{3},{4}'.format(
        results[i]['title'], ', '.join(results[i]['speakers']), results[i]['views'],
        results[i]['likes'], results[i]['dislikes']))
    else:
      print(u'{0:5d} {1:3d} {2:3d} {3} ({4})'.format(
        results[i]['views'], results[i]['likes'], results[i]['dislikes'], results[i]['title'],
        ', '.join(results[i]['speakers'])))

if __name__ == '__main__':
  show_video_stats(parse_args())

下方輸出的是在我寫完代碼時(shí)前25個(gè)觀看數(shù)最多的會(huì)議:

(venv) $ python pycon-scraper.py --sort views --max 25 --workers 8
Views +1 -1 Title (Speakers)
 3002 27  0 Keynote - Guido Van Rossum (Guido Van Rossum)
 2564 21  0 Computer science fundamentals for self-taught programmers (Justin Abrahms)
 2369 17  0 Ansible - Python-Powered Radically Simple IT Automation (Michael Dehaan)
 2165 27  6 Analyzing Rap Lyrics with Python (Julie Lavoie)
 2158 24  3 Exploring Machine Learning with Scikit-learn (Jake Vanderplas, Olivier Grisel)
 2065 13  0 Fast Python, Slow Python (Alex Gaynor)
 2024 24  0 Getting Started with Django, a crash course (Kenneth Love)
 1986 47  0 It's Dangerous to Go Alone: Battling the Invisible Monsters in Tech (Julie Pagano)
 1843 24  0 Discovering Python (David Beazley)
 1672 22  0 All Your Ducks In A Row: Data Structures in the Standard Library and Beyond (Brandon Rhodes)
 1558 17  1 Keynote - Fernando Pérez (Fernando Pérez)
 1449  6  0 Descriptors and Metaclasses - Understanding and Using Python's More Advanced Features (Mike Müller)
 1402 12  0 Flask by Example (Miguel Grinberg)
 1342  6  0 Python Epiphanies (Stuart Williams)
 1219  5  0 0 to 00111100 with web2py (G. Clifford Williams)
 1169 18  0 Cheap Helicopters In My Living Room (Ned Jackson Lovely)
 1146 11  0 IPython in depth: high productivity interactive and parallel python (Fernando Perez)
 1127  5  0 2D/3D graphics with Python on mobile platforms (Niko Skrypnik)
 1081  8  0 Generators: The Final Frontier (David Beazley)
 1067 12  0 Designing Poetic APIs (Erik Rose)
 1064  6  0 Keynote - John Perry Barlow (John Perry Barlow)
 1029 10  0 What Is Async, How Does It Work, And When Should I Use It? (A. Jesse Jiryu Davis)
 981 11  0 The Sorry State of SSL (Hynek Schlawack)
 961 12  2 Farewell and Welcome Home: Python in Two Genders (Naomi Ceder)
 958  6  0 Getting Started Testing (Ned Batchelder)

相關(guān)文章

  • 詳解Python爬取并下載《電影天堂》3千多部電影

    詳解Python爬取并下載《電影天堂》3千多部電影

    這篇文章主要介紹了Python爬取并下載《電影天堂》3千多部電影,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 深入理解python多線程編程

    深入理解python多線程編程

    進(jìn)程是資源分配的最小單位,他是操作系統(tǒng)進(jìn)行資源分配和調(diào)度運(yùn)行的基本單位。通俗理解:一個(gè)正在運(yùn)行的一個(gè)程序就是一個(gè)進(jìn)程,本文重點(diǎn)給大家介紹python多線程編程的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-04-04
  • python實(shí)現(xiàn)凱撒密碼

    python實(shí)現(xiàn)凱撒密碼

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)凱撒密碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • pyqt6實(shí)現(xiàn)QTimer定時(shí)器介紹和使用場(chǎng)景

    pyqt6實(shí)現(xiàn)QTimer定時(shí)器介紹和使用場(chǎng)景

    PyQt6中的QTimer是一個(gè)定時(shí)器類,用于在指定的時(shí)間間隔內(nèi)執(zhí)行某個(gè)操作,本文主要介紹了pyqt6實(shí)現(xiàn)QTimer定時(shí)器介紹和使用場(chǎng)景,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • 詳解Python2.x中對(duì)Unicode編碼的使用

    詳解Python2.x中對(duì)Unicode編碼的使用

    這篇文章主要介紹了詳解Python2.x中對(duì)Unicode編碼的使用,Python3中Unicode被作為默認(rèn)的編碼來使用,而在目前仍被廣泛應(yīng)用的Python2的版本中Unicode卻是一個(gè)在使用中需要注意的地方,需要的朋友可以參考下
    2015-04-04
  • python實(shí)現(xiàn)Virginia無密鑰解密

    python實(shí)現(xiàn)Virginia無密鑰解密

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)Virginia無密鑰解密,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-03-03
  • python實(shí)現(xiàn)ModBusTCP協(xié)議的client功能

    python實(shí)現(xiàn)ModBusTCP協(xié)議的client功能

    Modbus TCP 是一種基于 TCP/IP 協(xié)議棧的 Modbus 通信協(xié)議,它用于在工業(yè)自動(dòng)化系統(tǒng)中進(jìn)行設(shè)備之間的通信,只要通過pymodbus或pyModbusTCP任意模塊就可以實(shí)現(xiàn),本文采用pymodbus,感興趣的朋友跟隨小編一起看看吧
    2023-10-10
  • python Tensor和Array對(duì)比分析

    python Tensor和Array對(duì)比分析

    今天小編就為大家分享一篇python Tensor和Array對(duì)比分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-01-01
  • Python中的匿名函數(shù)使用簡(jiǎn)介

    Python中的匿名函數(shù)使用簡(jiǎn)介

    這篇文章主要介紹了Python中的匿名函數(shù)的使用,lambda是各個(gè)現(xiàn)代編程語言中的重要功能,需要的朋友可以參考下
    2015-04-04
  • 基于Python編寫簡(jiǎn)單實(shí)用的日志裝飾器

    基于Python編寫簡(jiǎn)單實(shí)用的日志裝飾器

    在寫代碼的時(shí)候,往往會(huì)漏掉日志這個(gè)關(guān)鍵因素,導(dǎo)致功能在使用的時(shí)候出錯(cuò)卻無法溯源。這個(gè)時(shí)候只要利用日志裝飾器就能解決,本文將用Python自制一個(gè)簡(jiǎn)單實(shí)用的日志裝飾器,需要的可以參考一下
    2022-05-05

最新評(píng)論