運行結(jié)果:
$ python 1.py
商品信息
北京二手平板電腦
國行99新 ipad air 出售 32g
2016-05-22
2000
-
0
[u'\u5927\u5174', u'-', u'\u4ea6\u5e84']
====================
商品信息
北京二手平板電腦
首信智能學(xué)習(xí)平板電腦
2016-05-22
1500
-
4
[u'\u4e30\u53f0', u'-', u'\u65b0\u53d1\u5730']
====================
商品信息
北京二手平板電腦
微軟 surface3 平板電腦
2016-05-22
3800
-
54
[u'\u6000\u67d4', u'-', u'\u96c1\u6816']
代碼:
#!/usr/bin/env python
# coding: utf-8
import time
from bs4 import BeautifulSoup
import requests
def get_views(detail_url):
"""獲取指定頁面的瀏覽量"""
infoid = detail_url.split("?")[0].split("/")[-1].strip("x.shtml")
views_url = "http://jst1.58.com/counter?infoid={}".format(infoid)
# print views_url
headers = {"Referer": detail_url}
views = requests.get(views_url, headers=headers).text.split("=")[2]
# print views
return views
def get_detail_url(pages, source):
"""獲取需要爬取的詳細(xì)商品url"""
urls = []
for i in range(pages):
infolist_url = "http://bj.58.com/pbdn/{source}/pn{page}".format(source=source, page=i+1)
infolist_page = requests.get(infolist_url)
time.sleep(1)
# print infolist_page
soup = BeautifulSoup(infolist_page.text, 'lxml')
detail_pages = soup.select("#infolist > table.tbimg > tr[logr] > td.img > a")
urls = [i.get('href') for i in detail_pages] # 第一條是推廣拯腮,跳過
# print urls
return urls[2:-1]
def get_detail_info(page=1, source=0):
"""獲取詳細(xì)頁面的信息"""
urls = get_detail_url(page, source)
for i in urls:
print u"商品信息"
detail_page = requests.get(i)
time.sleep(1)
detail_soup = BeautifulSoup(detail_page.text, 'lxml')
class_info = detail_soup.select("span.crb_i > a")[1].get_text()
print class_info
title = detail_soup.select("div.col_sub.mainTitle > h1")[0].get_text()
print title
creat_time = detail_soup.select(".time")[0].get_text()
print creat_time
price = detail_soup.select(".c_f50")[0].get_text()
print price
quality = detail_soup.select(".su_con > span")
print (quality[1].string).strip()
views = get_views(i)
print views
area_data = detail_soup.select("span.c_25d")
area = list(area_data[0].stripped_strings) if area_data else None
print area
print "="*20
# get_detail_url()
get_detail_info(page=1, source=0)
小結(jié)
獲取內(nèi)容
- body 和 head
不一定要從 HTML 的 body 中獲取,有些信息在 head 的 title 中就能夠得到
- CSS 選擇器 和 tag 對象
對于一些簡單結(jié)構(gòu)的網(wǎng)頁丙者,不必使用 BeautifulSoup 的 CSS 選擇器定位,可以直接通過 BeautifulSoup 的 tag 對象獲取元素的屬性家凯、值
- 選擇器的內(nèi)容
以 chrome 瀏覽器為例
在想要抓取的頁面元素上右擊-檢查疗疟,會自動在彈出的窗口中打開Elements
頁簽程帕,并定位到對應(yīng)的HTML 代碼住练,下方會顯示當(dāng)前標(biāo)簽的路徑,從html開始一直到當(dāng)前位置
從路徑最右側(cè)的元素開始愁拭,嘗試用最短的描述方式唯一地描述這個元素讲逛。比如僅僅用類``屬性``id
或添加少量元素標(biāo)簽a``div``li
。
可以使用>
指定直接子標(biāo)簽
岭埠,也可以不使用盏混,?只需要某個元素下的所有標(biāo)簽中有這個標(biāo)簽就可以匹配
判斷是否唯一過濾出需要的信息:選中點擊檢查
后彈出的窗口,ctrl + F
/command + F
調(diào)出搜索框枫攀,?輸入我們對元素的描述括饶,看高亮的是否都是我們想要獲取的元素,否則換一個描述再試
異步加載
這次最艱難的地方来涨,與爬取霉霉的異步加載數(shù)據(jù)不同,霉霉的異步加載請求是在加載完前一個頁面后可以通過向下查看手動進(jìn)行的启盛,在network
中可以很容易看到那條唯一的請求蹦掐,只不過需要注意異步是通過 XHR (一種 js 異步的方式)實現(xiàn)的。
58雖然也是異步(真實瀏覽量的獲取不影響其他 HTML僵闯、CSS 等的加載)卧抗,但異步的請求很多,因為對頁面異步加載實現(xiàn)的過程并不完全清楚鳖粟,找了很久也沒有發(fā)現(xiàn)社裆。后來看了作業(yè)講解視頻,只給了答案向图,卻沒有說過程泳秀。
于是自己進(jìn)行嘗試,通過<em id="totalcount">51</em>
的idtotalcount
,在頁面中找涉及的 js 內(nèi)容
從頁面獲取參數(shù)
<script type="text/javascript">
document.domain = "58.com";
var userid=GetCookieValue("UserID");
var username=GetCookieValue("UserName");
Counter58.userid=userid;
Counter58.uname=username;
Counter58.infoid=26019777369521;
Counter58.listControl="userlist";
Counter58.totalControl="totalcount";
Counter58.sid="517229375";
Counter58.px="";
Counter58.lid="1";
Counter58.cfpath="5,38484";
Counter58.create();
</script>
頁面 head 導(dǎo)入 js 腳本榄攀,指向一個鏈接
<script type="text/javascript" src="http://jst1.58.com/counter?infoid=26019777369521&userid=&uname=&sid=517229375&lid=1&px=&cfpath=5,38484"></script>
直接打開鏈接后的返回信息嗜傅,Counter58.total=0
就是瀏覽量的信息
Counter58.userlist[0]={uid:'0',uname:'',face:'',vt:''};Counter58.total=0
猜測:
當(dāng)Counter58.create();
運行后,會將參數(shù)傳遞給導(dǎo)入的 js 腳本檩赢,發(fā)送包含參數(shù)的請求吕嘀,獲得瀏覽量數(shù)據(jù),并替代 html 中的默認(rèn)值。
實際情況是否是這樣偶房,可能需要去學(xué) js趁曼,并等下周課程中老師的具體解釋了。
chrome 是一個很有用的前端開發(fā)工具棕洋,特意去做了一些了解:
異步信息的獲取
需要添加頭部字段
headers = {"Referer": detail_url}
Referer
可返回當(dāng)前文檔的 URL,否則向指定的 url 請求拍冠,無法獲得瀏覽量數(shù)據(jù)
條件表達(dá)式
又學(xué)習(xí)了一種很簡單尿这、優(yōu)雅的語法形式
x if i == j else y # 如果 i 等于 j,返回 x庆杜,否則返回 y