實戰(一)之使用自帶urllib和re正則表達式獲取電影詳情頁連接html
其實大多狀況下,python自帶的urllib和re正則表達式已經能夠知足咱們的平常需求了,可是,聰明的世人怎麼會知足於此呢,只有更好就沒有最好。因此,就誕生了requests和beautifulsoup這兩個做爲爬蟲的黃金組合。而python的魅力就在於此,你能夠找到不少好用易上手到讓你心頭一顫的第三方庫。html5
使用Pip能夠很方便的安裝:python
pip install requestsgit
pip install beautifulsoup4github
import requests
## get請求
r = requests.get('https://github.com/timeline.json')
r.json() ##若是是JSON 響應內容,使用r.json()會自動將json結果轉換成dict
r.content() ##二進制相應內容
headers = {'user-agent': 'my-app/0.0.1'} #定製請求頭
r = requests.get('https://github.com/timeline.json', headers=headers)
payload = {'key1': 'value1', 'key2': 'value2'} #傳遞url參數
r = requests.get("http://httpbin.org/get", params=payload)
## post請求
payload = {'key1': 'value1', 'key2': 'value2'} ## post數據
r = requests.post("http://httpbin.org/post", data=payload)
## 上傳文件
url = 'http://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}
r = requests.post(url, files=files)
複製代碼
更多詳細的請查看官方的中文文檔,詳細易懂權威。正則表達式
http://docs.python-requests.org/zh_CN/latest/user/quickstart.html編程
beautifulsoup能夠快速的去定位HTML文檔,HTML是用來描述網頁的一種超文本標記語言,不是一種編程語言。 若是你沒有HTML基礎,能夠去花一天的時間瞭解下。 菜鳥教程--HTMLjson
http://www.runoob.com/html/html-tutorial.htmlbash
如今假設知道了HTML是個什麼東西,你會發現HTML就是由一層又一層的tag組成,每一個tag節點有本身的class屬性或者其餘屬性、本身的父tag、子tag以及兄弟tag,而beautifulsoup的做用就是經過這種蛛絲馬跡,輕易的把你要的兇手。。哦不目標節點揪出來,免去了寫正則表達式的繁瑣噩夢。多線程
beautifulsoup對HTML的解釋是依賴第三方解釋庫的,經常使用的有html.parser、lxml、支持xml解釋的lxml-xml、html5Lib,各有優缺點,根據個人經驗,有時候使用beautifulsoup返回的待處理文本,會缺乏一些tag節點,可是你又肯定這不是動態加載的話,其實這是由於解釋器沒法解釋,直接跳過致使的,這時候,能夠更換解釋器嘗試一下。
我這裏只用下find和find_all做爲實例,詳細的用法請去權威易懂的官方文檔。 畢竟作搬運工是件很累且無心義的事情。
http://beautifulsoup.readthedocs.io/zh_CN/latest/
from bs4 import BeautifulSoup
##配合requests
r = requests.get('http://www.douban.com')
##一鍋待處理的soup湯
soup = BeautifulSoup(r.content,'lxml') #使用lxml解釋庫
print(soup)
複製代碼
咱們會獲得以下的soup體,而後定位到紅色框的a塊。
經過屬性定位查找該節點 (find)
a = soup.find('a',attrs={'class':'lnk-book'})
print(a)
print('連接: '+a['href'])
print('文字: '+a.text)
複製代碼
返回包含全部該節點的列表(find_all)
a_s = soup.find_all('a')
print (a_s)
複製代碼
提示:有時候須要先將目標範圍逐層縮小,這樣容易獲取目標節點。
一、 咱們點擊底部的頁碼,會發現頁數是25的倍數,從0開始,這樣咱們就能夠構造對應頁的url了。
二、咱們定位到每頁,查找書本的信息,獲取對應的url,下圖爲每頁爬取到的書本詳情頁url。
三、在圖書的詳情頁,咱們定位到以下元素。獲取該書的書名,評分和評分人數。
# -*- coding:utf-8 -*-
#author:waiwen
#email:iwaiwen@163.com
#time: 2017/12/3 12:27
from bs4 import BeautifulSoup
import requests
import random
#uer_agent庫,隨機選取,防止被禁
USER_AGENT_LIST = [
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
]
#請求網頁的代碼整合
def get_response(url):
#random.choice從一個集合中隨機選出請求頭
headers = {'user-agent':random.choice(USER_AGENT_LIST)}
resp = requests.get(url,headers=headers)
resp.raise_for_status()
soup = BeautifulSoup(resp.content, 'lxml')
return soup
#找到每本書的連接
def get_book_url(page):
if page>10:
return []
num=(page-1)*25
url ='https://book.douban.com/top250?start=%s'%str(num)
soup = get_response(url)
book_div = soup.find('div', attrs={'class': 'indent'})
books = book_div.find_all('tr', attrs={'class': 'item'})
urls = [ book.td.a['href'] for book in books ]
print('獲取第%s頁'%page,urls)
return urls
#得到每本書的信息
def get_book_info(book_url):
soup = get_response(book_url)
div_info = soup.find('div',attrs={'id':'info'})
book_author = div_info.a.text.split(' ')[-1] #將空格去除
book = soup.find('div',attrs={'class':'rating_wrap clearbox'})
book_name= soup.find('span',attrs={'property':'v:itemreviewed'}).text
book_grade = book.find('strong',attrs={'class':'ll rating_num '}).text
book_man = book.find('a',attrs={'class':'rating_people'}).span.text
book_info ={}
book_info['name']=book_name
book_info['author']=book_author
book_info['rating_num'] = int(book_man)
book_info['grade'] = float(book_grade)
print(book_info)
return book_info
if __name__ == '__main__':
all_urls = []
#從第1頁到第10頁爬取,連接拼接到一塊兒。
for page in range(1,11):
urls = get_book_url(page)
all_urls = all_urls+urls
print('獲取到的連接數:',len(all_urls))
out=''
for url in all_urls:
try:
info = get_book_info(url)
except Exception as e:
print(e)
continue
out=out+str(info)+'\n'
with open('douban_book_top250.txt','w') as f: #輸出到TXT文件
f.write(out)
複製代碼
分析頁面,找到目標元素所在的tag節點,記錄其屬性,經過beautifulsoup的find和find_all找到該區域,而後進行相應的提取。這個過程當中,要說明一下,使用單線程阻塞爬取250本書的信息,比較耗時,計劃後面將會使用多線程進行改進,敬請期待喲。