打卡:大作業(yè)|爬取一頁(yè)商品數(shù)據(jù)

目標(biāo):

爬取某8的一頁(yè)商品信息,介于老師給的網(wǎng)址全是轉(zhuǎn)轉(zhuǎn)信息因此我自己選擇了一個(gè)賣狗的頁(yè)面(捂臉)
界面如下:(排除了心寵的所有推廣)

網(wǎng)頁(yè)截圖

我們需要爬取商家和個(gè)人兩個(gè)部分的詳情頁(yè)信息

爬取結(jié)果:

個(gè)人詳情頁(yè)網(wǎng)址
商家詳情頁(yè)網(wǎng)址
個(gè)人部分信息
商家部分信息

難點(diǎn)

  • 瀏覽人數(shù)的爬取
  • 爬取的網(wǎng)址跟跳轉(zhuǎn)的網(wǎng)址不同
  • 不同網(wǎng)頁(yè)完善的信息不同(比如有的有電話有的沒(méi)有)
  • 個(gè)人和商家版的詳情頁(yè)元素位置有輕微區(qū)別(比如同一個(gè)位置會(huì)存放不同內(nèi)容信息)
  • 爬取的文本有大量/t/r/n的信息
  • 挑戰(zhàn)自己爬了下需要點(diǎn)擊才能顯示的電話號(hào)碼

代碼

from bs4 import BeautifulSoup
import time
import requests


def get_urls(path,name_num):
    respond = requests.get(path)
    soup = BeautifulSoup(respond.text, 'lxml')
    pre_urls = soup.select('''td.t > a[onclick="clickLog('from=pc_cwgou_list_wenzi');"]''')
    i = 0
    urls = []
    file = open('./urls{}.txt'.format(name_num),'a')
    for url in pre_urls:
        i = i + 1
        href = url.get('href')
        urls.append(href)
        text = url.get_text()
        print(i,' ',href,text)
        file.write(str(i)+' '+ href +'\n'+text+'\n\n')
    file.close()
    return urls

def get_views(url):
    time.sleep(2)
    get_num1 = url.split('x.shtml')
    get_num2 = get_num1[0].split('dog/')[-1]
    api = 'http://jst1.58.com/counter?infoid={}'.format(get_num2)
    headers = {
        'Referer':'http://m.58.com/tj/dog/{}'.format(get_num2),
        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1'
    }
    js = requests.get(api,headers = headers)
    views = js.text.split('total=')[-1]
    return views

def detail (path, count, Hkind_judge) :
    respond = requests.get(path)
    views = get_views(respond.url)
    soup = BeautifulSoup(respond.text,'lxml')
    url_kind = soup.select('#header > div.breadCrumb.f12 > span:nth-of-type(4) > a')
    kind = soup.select('body > div.content_quanbu > div.zhanshi_top.clearfix > div.zhanshi_top_l.fl.clearfix > div.col_sub.sumary.fl > ul > li:nth-of-type({}) > div.su_con > span:nth-of-type(1)'.format(3 if Hkind_judge == 0 else 4))
    title = soup.select('body > div.content_quanbu > div.col_sub.mainTitle > div > h1')
    date = soup.select('#index_show > ul.mtit_con_left.fl.clearfix > li.time.fl > span')
    num = soup.select('span.zhishu')
    pos = soup.select('span.dizhi')
    host = soup.select('span.lianxiren > a')
    phone = soup.select('#t_phone')
    if Hkind_judge == 0:
        host_kind = '個(gè)人'
    elif Hkind_judge == 1:
        host_kind = '商家'
    else:
        host_kind = '未知'
    list = [
        '網(wǎng)頁(yè)分類:'+ url_kind[0].get_text() if url_kind else '網(wǎng)頁(yè)分類:None',
        '網(wǎng)頁(yè)標(biāo)題:'+ title[0].get_text() if title else '網(wǎng)頁(yè)標(biāo)題:None',
        '發(fā)帖日期:'+ date[0].get_text() if date else '發(fā)帖日期:None',
        '店家類型:'+ host_kind,
        '瀏覽次數(shù):'+ views,
        '寵物種類:'+ kind[0].get_text().replace('\t', '').replace('\n','').replace(' ','') if kind else '寵物種類:None',
        '主人:'+ host[0].get_text() if host else '主人:None',
        '電話:'+ phone[1].get_text() if len(phone) > 1  else '電話:None',
        '只數(shù):'+ num[0].get_text() if num else '只數(shù):None',
        '位置:'+ pos[0].get_text() if pos else '位置:None'
    ]
    print(list)
    file_path = './imformation.txt'
    file = open(file_path, 'a')
    file.write('第'+str(count)+'個(gè)\n')
    for i in list:
        file.write(i+'\n')
    file.write('\n\n')
    file.close()

path1 = 'http://bj.58.com/dog/1/?PGTID=0d3000fc-0000-13b1-ca3b-4d326020e12d&ClickID=1'
path0 = 'http://bj.58.com/dog/0/?PGTID=0d3000fc-0000-13b1-ca3b-4d326020e12d&ClickID=1'

urls0 = get_urls(path0,'0')
count = 0
for url0 in urls0:
    time.sleep(2)
    count = count + 1
    detail(url0,count,Hkind_judge = 0)

urls1 = get_urls(path1,'1')
count = 0
for url1 in urls1:
    time.sleep(2)
    count = count + 1
    detail(url1, count,Hkind_judge = 1)

其實(shí)個(gè)人和商家兩個(gè)部分的網(wǎng)址也是可以用format來(lái)做到的,我這里一開(kāi)始貪圖簡(jiǎn)單沒(méi)有用循環(huán)遭笋,但是后期發(fā)現(xiàn)很多地方要用到0、1兩個(gè)變量(包括兩份網(wǎng)址txt的命名和商品詳情里出處的判斷)

總結(jié):

說(shuō)一下上面難點(diǎn)的解決方案

  • 瀏覽人數(shù):
    先打開(kāi)檢查是偷,sources星压,刷個(gè)新晒喷,可以找到一個(gè)js文件愚争,把這個(gè)地址復(fù)制下來(lái)映皆,進(jìn)行g(shù)et請(qǐng)求就可以獲得這個(gè)js瀏覽量的返回(即數(shù)據(jù)部分最后的total = xxxx)
    這個(gè)文件的Infoid一串?dāng)?shù)字和網(wǎng)址的id是一致的挤聘,因此把網(wǎng)址的id取出來(lái)轰枝,就可以用fomat批量獲取js啦
    但是我還遇到一個(gè)問(wèn)題,就是照做了之后還是爬不到组去,返回total=0鞍陨,這個(gè)時(shí)候加個(gè)Header的Referer試試就可以


    檢查界面
def get_views(url):
    time.sleep(2)
    get_num1 = url.split('x.shtml')
    get_num2 = get_num1[0].split('dog/')[-1]
    api = 'http://jst1.58.com/counter?infoid={}'.format(get_num2)
    headers = {
        'Referer':'http://m.58.com/tj/dog/{}'.format(get_num2),
        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1'
    }
    js = requests.get(api,headers = headers)
    views = js.text.split('total=')[-1]
    return views
  • 那么問(wèn)題來(lái)了,要得到網(wǎng)址中的id从隆,但是看我的結(jié)果txt诚撵,發(fā)現(xiàn)爬取的第一個(gè)網(wǎng)頁(yè)是和下面不一樣,沒(méi)有一串?dāng)?shù)字的键闺,這是因?yàn)檫@是跳轉(zhuǎn)前的網(wǎng)址寿烟,我們無(wú)法判斷得到的網(wǎng)址是否還有一次跳轉(zhuǎn),所以解決方法是取瀏覽量之前辛燥,取已打開(kāi)詳情頁(yè)的網(wǎng)址進(jìn)行分析(已跳轉(zhuǎn)完成的)
respond = requests.get(path)
views = get_views(respond.url)
  • 不同網(wǎng)頁(yè)完善的信息不同筛武,所以一旦沒(méi)有獲取到需要的內(nèi)容,程序會(huì)死掉哦~怎么解決這個(gè)問(wèn)題呢挎塌,就因?yàn)檫@個(gè)調(diào)試到了今天(所以遲交了作業(yè)徘六,抱歉)
    解決方法是要養(yǎng)成每個(gè)信息都要判斷是否存在的習(xí)慣
    突然聯(lián)系到直播的時(shí)候老師有個(gè)這樣的習(xí)慣,在每個(gè)獲取信息輸出之前榴都,會(huì)
    判斷列表是否為空待锈,像這樣:if list else None
 list = [
        '網(wǎng)頁(yè)分類:'+ url_kind[0].get_text() if url_kind else '網(wǎng)頁(yè)分類:None',
        '網(wǎng)頁(yè)標(biāo)題:'+ title[0].get_text() if title else '網(wǎng)頁(yè)標(biāo)題:None',
        '發(fā)帖日期:'+ date[0].get_text() if date else '發(fā)帖日期:None',
        '店家類型:'+ host_kind,
        '瀏覽次數(shù):'+ views,
        '寵物種類:'+ kind[0].get_text().replace('\t', '').replace('\n','').replace(' ','') if kind else '寵物種類:None',
        '主人:'+ host[0].get_text() if host else '主人:None',
        '電話:'+ phone[1].get_text() if len(phone) > 1  else '電話:None',
        '只數(shù):'+ num[0].get_text() if num else '只數(shù):None',
        '位置:'+ pos[0].get_text() if pos else '位置:None'
    ]

我用List存放是為了輸出的txt格式好看一點(diǎn),如果要輸出其他的要用字典什么的啦
可以看到個(gè)人信息頁(yè)面很多東西都是None因?yàn)樗麄儧](méi)有寫(xiě)

  • 個(gè)人和商家版的詳情頁(yè)元素位置有輕微區(qū)別嘴高,這個(gè)導(dǎo)致我爬品種的時(shí)候竿音,總是會(huì)一部份顯示防疫的內(nèi)容,一部分顯示品種
    解決辦法是判斷當(dāng)前是商家版還是個(gè)人版拴驮,改變位置春瞬,我這里用format(Hkind_judge是主人類型判斷...名字奇怪了點(diǎn)哈)
kind = soup.select('body > div.content_quanbu > div.zhanshi_top.clearfix > div.zhanshi_top_l.fl.clearfix > div.col_sub.sumary.fl > ul > li:nth-of-type({}) > div.su_con > span:nth-of-type(1)'.format(3 if Hkind_judge == 0 else 4))
  • 爬取的文本有大量/t/r/n的信息,要怎么刪除呢莹汤?(說(shuō)的就是品種信息)
    刪除的方法其實(shí)有很多種快鱼,我這里用了最粗暴的repla
'寵物種類:'+ kind[0].get_text().replace('\t', '').replace('\n','').replace(' ','') if kind else '寵物種類:None'
  • 挑戰(zhàn)自己爬了下需要點(diǎn)擊才能顯示的電話號(hào)碼
    然后我發(fā)現(xiàn)并不難,因?yàn)檫@個(gè)沒(méi)有用js控制,直接就放在網(wǎng)頁(yè)源碼抹竹,所以只要判斷好它的位置就可以线罕,要小心的是所有select結(jié)果都是列表,沒(méi)把握需要的信息在哪里的窃判,就先print出來(lái)
    這里遇到的問(wèn)題其實(shí)就是有的詳情沒(méi)有給電話钞楼,但是得到的列表依然是有一個(gè)值的,所以這里不是判斷為空袄琳,而是判斷元素個(gè)數(shù)是否大于1
'電話:'+ phone[1].get_text() if len(phone) > 1  else '電話:None'
  • 變量名比較混亂抱歉询件,因?yàn)闀?huì)的單詞實(shí)在不夠多(捂臉),然后也忘了爬價(jià)格唆樊,不過(guò)我覺(jué)得價(jià)格應(yīng)該也不難宛琅,所以就不管了
    這一次大作業(yè)確實(shí)發(fā)現(xiàn)了很多之前的網(wǎng)頁(yè)不存在的問(wèn)題,做起來(lái)比較辛苦逗旁,但是好有成就感~
    順便為了保護(hù)嘿辟,每個(gè)請(qǐng)求都加了time.sleep(2)保護(hù),但是這個(gè)方法速度實(shí)在是慢了點(diǎn)
  • 嘛這周的作業(yè)也要加油了(づ ̄ 3 ̄)づ
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末片效,一起剝皮案震驚了整個(gè)濱河市红伦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌淀衣,老刑警劉巖昙读,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異膨桥,居然都是意外死亡蛮浑,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門(mén)国撵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)陵吸,“玉大人,你說(shuō)我怎么就攤上這事介牙∽吵妫” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵环础,是天一觀的道長(zhǎng)囚似。 經(jīng)常有香客問(wèn)我,道長(zhǎng)线得,這世上最難降的妖魔是什么饶唤? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮贯钩,結(jié)果婚禮上募狂,老公的妹妹穿的比我還像新娘办素。我一直安慰自己,他們只是感情好祸穷,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布性穿。 她就那樣靜靜地躺著,像睡著了一般雷滚。 火紅的嫁衣襯著肌膚如雪需曾。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天祈远,我揣著相機(jī)與錄音呆万,去河邊找鬼。 笑死车份,一個(gè)胖子當(dāng)著我的面吹牛谋减,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播躬充,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼逃顶,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了充甚?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤霸褒,失蹤者是張志新(化名)和其女友劉穎伴找,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體废菱,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡技矮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了殊轴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片衰倦。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖旁理,靈堂內(nèi)的尸體忽然破棺而出樊零,到底是詐尸還是另有隱情,我是刑警寧澤孽文,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布驻襟,位于F島的核電站,受9級(jí)特大地震影響芋哭,放射性物質(zhì)發(fā)生泄漏沉衣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一减牺、第九天 我趴在偏房一處隱蔽的房頂上張望豌习。 院中可真熱鬧存谎,春花似錦、人聲如沸肥隆。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)巷屿。三九已至固以,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間嘱巾,已是汗流浹背憨琳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留旬昭,地道東北人篙螟。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像问拘,于是被迫代替她去往敵國(guó)和親遍略。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容