深刻Ajax署理的Java Servlet的完成詳解。本站提示廣大學習愛好者:(深刻Ajax署理的Java Servlet的完成詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是深刻Ajax署理的Java Servlet的完成詳解正文
1.裝置BeautifulSoup4
easy_install裝置方法,easy_install須要提早裝置
easy_install beautifulsoup4
pip裝置方法,pip也須要提早裝置.另外PyPi中還有一個名字是 BeautifulSoup 的包,那是 Beautiful Soup3 的宣布版本.在這裡不建議裝置.
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.百度.com/p/3537654215' # 下載網頁 html = urllib.urlopen(url) content = html.read() html.close() # 應用BeautifulSoup婚配圖片 html_soup = BeautifulSoup(content) # 圖片代碼我們在[Python爬蟲基本1--urllib]( http://blog.xiaolud.com/2015/01/22/spider-1st/ "Python爬蟲基本1--urllib")外面曾經剖析過了 # 相較經由過程正則表達式去婚配,BeautifulSoup供給了一個更簡略靈巧的方法 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
很簡略,代碼正文外面曾經說明的很清晰了.BeautifulSoup供給了一個更簡略靈巧的方法,去剖析網站源碼,更快獲得圖片link.
3.爬取實例
3.1根本的抓取技巧
在寫一個爬蟲劇本時,第一件工作就是手動不雅察要抓取的頁面來肯定數據若何定位。
起首,我們要看一看在 http://pyvideo.org/category/50/pycon-us-2014 上的 PyCon 年夜會視頻列表。檢討這個頁面的 HTML 源代碼我們發明視頻列表的成果差不多是長如許的:
<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>
那末第一個義務就是加載這個頁面,然後抽取每一個零丁頁面的鏈接,由於到 YouTube 視頻的鏈接都在這些零丁頁面上。
應用requests來加載一個 web 頁面長短常簡略的:
import requests response = requests.get('http://pyvideo.org/category/50/pycon-us-2014')
就是它!在這個函數前往後就可以從response.text中取得這個頁面的 HTML 。
下一個義務是抽取每個零丁視頻頁面的鏈接。經由過程 BeautifulSoup 應用 CSS 選擇器語法就可以完成它,假如你是客戶端開辟者的話你能夠對這會很熟習。
為了取得這些鏈接,我們要應用一個選擇器,它能抓取在每個 id 為video-summary-data的<div>中一切的<a>元素。因為每一個視頻都有幾個<a>元素,我們將只保存那些 URL 以/video開首的<a>元素,這些就是獨一的零丁視頻頁面。完成上述尺度的 CSS 選擇器是div.video-summary-data a[href^=/video]。上面的代碼片斷經由過程 BeautifulSoup 應用這個選擇器來取得指向視頻頁面的<a>元素:
import bs4 soup = bs4.BeautifulSoup(response.text) links = soup.select('div.video-summary-data a[href^=/video]')
由於我們真正關懷的是這個鏈接自己而不是包括它的<a>元素,我們可使用列表解析來改良上述代碼。
links = [a.attrs.get('href') for a in soup.select('div.video-summary-data a[href^=/video]')]
如今,我們曾經有了一個包括一切鏈接的數組,這些鏈接指向了每一個零丁頁面。
上面這段劇本整頓了今朝我們提到的一切技巧:
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())
假如你運轉下面這段劇本你將會取得一個全是 URL 的數組。如今我們須要去解析每一個 URL 以取得更多關於每場 PyCon 會議的信息。
3.2抓取相連頁面
下一步是加載我們的 URL 數組中每個頁面。假如你想要看看這些頁面長甚麼樣的話,這兒是個樣例:http://pyvideo.org/video/2668/writing-restful-web-services-with-flask。沒錯,那就是我,那是我會議中的一個!
從這些頁面我們可以抓取到會議的題目,在頁面的頂部能看到它。我們也能夠從側邊欄取得演講者的姓名和 YouTube 的鏈接,側邊欄在嵌入視頻的右下方。獲得這些元素的代碼展現鄙人方:
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()
關於這個函數須要留意的一些工作:
從首頁抓取的 URL 是絕對途徑,所以root_url須要加到後面。
年夜會題目是從 id 為videobox的<div>裡的<h3>元素中取得的。留意[0]是必需的,由於挪用select()前往的是一個數組,即便只要一個婚配。
演講者的姓名和 YouTube 鏈接的獲得方法與首頁上的鏈接獲得方法相似。
如今就剩下從每一個視頻的 YouTube 頁面抓取不雅看數了。接著下面的函數寫下去實際上是異常簡略的。異樣,我們也能夠抓取 like 數和 dislike 數。
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
上述挪用soup.select()函數,應用指定了 id 名字的選擇器,收集到了視頻的統計數據。然則元素的文本須要被處置一下能力釀成數字。斟酌不雅看數的例子,在 YouTube 上顯示的是"1,344 views"。用一個空格離開(split)數字和文本後,只要第一部門是有效的。因為數字裡有逗號,可以用正則表達式過濾失落任何不是數字的字符。
為了完成爬蟲,上面的函數挪用了之條件到的一切代碼:
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並行處置
下面到今朝為止的劇本任務地很好,然則有一百多個視頻它就要跑個一會兒了。現實上我們沒做甚麼任務,年夜部門時光都糟蹋在了下載頁面上,在這段時光劇本時被壅塞的。假如劇本能同時跑多個下載義務,能夠就會更高效了,是嗎?
回想其時寫一篇應用 Node.js 的爬蟲文章的時刻,並發性是隨同 JavaScript 的異步特征自帶來的。應用 Python 也能做到,不外須要顯示地指定一下。像這個例子,我將開啟一個具有8個可並行化過程的過程池。代碼出人意表的簡練:
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個任務過程期待分派義務運轉。為何是8個?這是我電腦上核數的兩倍。其時試驗分歧年夜小的過程池時,我發明這是最好的年夜小。小於8個使劇本跑的太慢,多於8個也不會讓它更快。
挪用pool.map()相似於挪用慣例的map(),它將會對第二個參數指定的迭代變量中的每一個元素挪用一次序遞次一個參數指定的函數。最年夜的分歧是,它將發送這些給過程池所具有的過程運轉,所以在這個例子中八個義務將會並交運行。
節儉上去的時光是相當年夜的。在我的電腦上,第一個版本的劇本用了75秒完成,但是過程池的版本做了異樣的任務只用了16秒!
3.4完成爬蟲劇本
我終究版本的爬蟲劇本在取得數據後還做了更多的工作。
我添加了一個--sort敕令行參數去指定一個排序尺度,可以指定views,likes或許dislikes。劇本將會依據指定屬性對成果數組停止遞加排序。另外一個參數,--max代表了要顯示的成果數的個數,萬一你只想看排名靠前的幾條罷了。最初,我還添加了一個--csv選項,為了可以輕松地將數據導到電子制表軟件中,可以指定命據以 CSV 格局打印出來,而不是表對齊格局。
完全劇本顯示鄙人方:
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())
下方輸入的是在我寫完代碼時前25個不雅看數最多的會議:
(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)