先開始說一段廢話吧。。。
我是從3月中旬開始接觸Python。當時我想學習如何去做出比較專業的數據分析圖,然后我家人說R語言和Python都可以做出圖來。但他建議學Python。我在網上找學習的資料,偶爾之間看到python可以實現爬蟲功能。正如彭老師的簡書中寫到的“學習Python,比較好快速找到應用的場景”??吹脚老x取得各個網頁大數據后做的數據分析,這也是我學習的興趣所在。學習過程饒了不少彎路,以下是我自己的一些教訓吧。
python語言學習經驗:
1、基礎知識要扎實,先要學習一些python的基本操作
參考一本《簡明 Python 教程》的文章,因為學過C語言,有些編程的基本常識,所以著重看了些:
1)數據結構(列表,元組,字典)
2)控制流(if,for,try...except)
3)函數(變量,參數,實參,形參,參數的傳遞)
4)類
這些在爬蟲中反復應用到,一定要學習扎實,不要一開始就去找別人做的爬蟲案例。先把基礎知識點過一遍,至少知道python的語言結構是怎么樣的。會打python代碼
2、了解爬蟲的原理。學習哪些關鍵知識點
我的經驗是先了解html的網頁代碼,再搞清楚爬蟲的過程,然后一個一個知識點去查資料,去練習??梢栽诮K端先從幾行小代碼開始練習。最后在做一個小爬蟲,然后慢慢變大爬蟲,哈哈。。。。(我之前就是沒有搞清楚怎么入手學爬蟲,饒了一圈回到原點)
爬蟲的抓取過程:
先獲得網頁地址----〉解析網頁代碼----〉抓取和提取網頁內容---〉存儲數據 是不是很簡單。。。。
小爬蟲變大爬蟲:
單頁爬蟲----〉多頁爬蟲----〉“迭代”爬蟲(就是有爬取鏈接頁面底下的頁面)----〉異步加載爬蟲---〉scrapy爬蟲(目前正在攻克中。。。)
爬蟲的小知識點主要在于抓取和提取網頁內容:
1)BeatifulSoup
說到這個“美麗湯“,我真是又愛又恨。我第一次在終端用的時候就不能運行。大受打擊。原因是引入這個類的時候沒有區分大小
錯誤:
from bs4 import beautifulsoup
正確:
from bs4 import BeautifulSoup
#bs4是一個python的庫,BeautifulSoup是這個庫里的一個類
知識點1:
soup.find_all('tag.name', class_='class_ value')
soup.find_all('tag.name',attrs ={'class':'class_ value'})
舉例:
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story"><a class="sister" id="link1">Elsie</a>
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
soup = BeautifulSoup(html_doc)
print soup.find_all('title') #提取'title'標簽的所有列表
print soup.find_all('p',class_='title') #提取含‘p'標簽的且'class'屬性是'title'的所有列表
print soup.find_all('a') #提取'a'標簽的所有列表
print soup.find_all(id="link2") #提取id的'屬性是"link2"的所有列表
返回值為:
[<title>The Dormouse's story</title>]
[<p class="title"><b>The Dormouse's story</b></p>]
[<a class="sister" id="link1">Elsie</a>, <a class="sister" id="link2">Lacie</a>, <a class="sister" id="link3">Tillie</a>]
[<a class="sister" id="link2">Lacie</a>]
知識點2:
soup.select(tag.name1 tag.name2 tag.name3) #提取tag.name1標簽下的tag.name2標簽下的tag.name3的列表
soup.select('#****')
soup.select('.****')
soup.select('tag.name #***')
舉例:
soup.select('#sponsor') #通過id查找,搜索 id 為 sponsor 的標簽列表
#可以在chrome網頁抓包中點擊你要抓的那個tag,看到整個tag的層次(見圖“抓包tag“)
soup.select('.ebox') .這個點表示查詢class="ebox"的,所有標簽內容
soup.select('div #index_nav') 表示尋找div標簽中id為index_nav的標簽內容。
為了方便查找自己抓取的內容,以上可以把空格改為' 〉':
舉例:
soup.select("div > #index_nav")
- Xpath知識點
·在網頁源代碼中右鍵,Copy XPath
·// 定位根節點
·/ 往下層尋找
·提取文本內容:/text()
·提取屬性內容: /@xxxx
·以相同的字符開頭 starts-with(@屬性名稱, 屬性字符相同部分)
·標簽套標簽 string(.)
3)正則表達式
目前我還不是很會,所以不做描述
開始爬啦--爬取“簡書7日熱門“
我在這里就不做具體講解,可以看一下其他童鞋在爬蟲作業專題做的作業,就我犯得一些錯誤和大家分享一下吧
#-*-coding:'utf-8'-*-
import requests
from lxml import etree
import csv
import re
import json
import sys
reload(sys)
sys.setdefaultencoding('utf8')
base_url='http://www.lxweimin.com/'
def information(url):
html=requests.get(url).content
selector=etree.HTML(html)
datas=selector.xpath('//ul[@class="note-list"]/li')
infos=[]
for data in datas:
detail_url=data.xpath('a/@href')
if detail_url:
detail_url1=detail_url[0]
detail_url1='http://www.lxweimin.com'+detail_url1
info=information2(detail_url1)
infos.append(info)
return infos
def information2(url):
info=[]
html=requests.get(url).content
selector=etree.HTML(html)
user=selector.xpath('//span[@class="name"]/a/text()')[0]
title=selector.xpath('//div[@class="article"]/h1[@class="title"]/text()')[0]
#read_qty = selector.xpath('//div[@class="meta"]/span[2]/text()')[0]
#read_qty=re.findall('"views_count":(.*?),', html, re.S)[0]
view_qty=re.findall('"views_count":(.*?),', html, re.S)[0]
comment_qty=re.findall('"comments_count":(.*?),', html, re.S)[0]
like_qty=re.findall('"likes_count":(.*?),', html, re.S)[0]
id=re.findall('"id":(.*?),', html, re.S)[0]
reward_url='http://www.lxweimin.com/notes/%s/rewards?count=20' %id
html_reward=requests.get(reward_url).text
reward_detail=json.loads(html_reward)
reward_qty=reward_detail['rewards_count']
html_collection_url='http://www.lxweimin.com/notes/%s/included_collections?page=1' %id
collection=collections(html_collection_url,id)
info.append(user)
info.append(title)
info.append(view_qty)
info.append(comment_qty)
info.append(like_qty)
info.append(reward_qty)
info.append(collection)
return info
def collections(url,id):
html=requests.get(url).content
collection_detail=json.loads(html)
pages=collection_detail['total_pages']
collection_urls=['http://www.lxweimin.com/notes/{}/included_collections?page={}'.format(id,str(i)) for i in range(1,pages+1)]
datas = []
for url in collection_urls:
html_collection=requests.get(url).content
collection_detail=json.loads(html_collection)
for one in collection_detail['collections']:
datas.append(one['title'])
data=','.join(datas)
return(data)
if __name__=='__main__':
urls=["http://www.lxweimin.com/trending/weekly?&page={}".format(i) for i in range(1,27)]
csvfile=file('sevenday.csv','wb')
writer=csv.writer(csvfile)
#infos=[]
for url in urls:
resources=information(url)
#infos.append(resoure)
for resource in resources:
writer.writerow(resource)
csvfile.close()
每一個小程序都是在不斷的調試不斷的查資料中進行的。
錯誤1:(印象也是最深刻的)
對xpath的抓數據理解不夠透徹,我想要抓取的是首頁的每個標題的鏈接,看一下網頁代碼:
分析:每一個href都存放在a標簽下,a標簽又存放在div.content下,思路:把所有li都提取到。然后for循環爬取li下的a下的href信息。(具體可以看圖片底部的標簽name)。我們可以按照以下來做:
datas=selector.xpath('//ul[@class="note-list"]/li')
for data in datas:
detail_url=data.xpath('a/@href')
我當時寫成了:
datas=selector.xpath('//div[@class="list-container"]/ul[@class="note-list"]')
for data in datas:
detail_url=data.xpath('li/a/@href')
經過測試len[datas]結果是0,原因是其實提取了ul下滿足class="note-list"的標簽。并沒有爬取到li這一層
錯誤2:提取分頁鏈接的url時候,發現程序一直出現報錯。
教訓:需要學會調試,從大的范圍開始調試,在一點縮小范圍,找出問題所在
print 所有的 detail_url時候發現,有的url為空,故需要做一個判斷是否為空。
for data in datas:
detail_url=data.xpath('a/@href')
if detail_url:
detail_url1=detail_url[0]
總結
謝謝程老師彭老師的指導幫助!
還有就是多看!多想!多問!最重要的是多做?。。?/p>