打卡:大作业|爬取一页商品数据

目标:

爬取某8的一页商品信息,介于老师给的网址全是转转信息因此我自己选择了一个卖狗的页面(捂脸)
界面如下:(排除了心宠的所有推广)

网页截图

我们需要爬取商家和个人两个部分的详情页信息

爬取结果:

个人详情页网址
商家详情页网址
个人部分信息
商家部分信息

难点

  • 浏览人数的爬取
  • 爬取的网址跟跳转的网址不同
  • 不同网页完善的信息不同(比如有的有电话有的没有)
  • 个人和商家版的详情页元素位置有轻微区别(比如同一个位置会存放不同内容信息)
  • 爬取的文本有大量/t/r/n的信息
  • 挑战自己爬了下需要点击才能显示的电话号码

代码

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 = '个人'
    elif Hkind_judge == 1:
        host_kind = '商家'
    else:
        host_kind = '未知'
    list = [
        '网页分类:'+ url_kind[0].get_text() if url_kind else '网页分类:None',
        '网页标题:'+ title[0].get_text() if title else '网页标题:None',
        '发帖日期:'+ date[0].get_text() if date else '发帖日期:None',
        '店家类型:'+ host_kind,
        '浏览次数:'+ 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',
        '只数:'+ num[0].get_text() if num else '只数:None',
        '位置:'+ pos[0].get_text() if pos else '位置:None'
    ]
    print(list)
    file_path = './imformation.txt'
    file = open(file_path, 'a')
    file.write('第'+str(count)+'个\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)

其实个人和商家两个部分的网址也是可以用format来做到的,我这里一开始贪图简单没有用循环,但是后期发现很多地方要用到0、1两个变量(包括两份网址txt的命名和商品详情里出处的判断)

总结:

说一下上面难点的解决方案

  • 浏览人数:
    先打开检查,sources,刷个新,可以找到一个js文件,把这个地址复制下来,进行get请求就可以获得这个js浏览量的返回(即数据部分最后的total = xxxx)
    这个文件的Infoid一串数字和网址的id是一致的,因此把网址的id取出来,就可以用fomat批量获取js啦
    但是我还遇到一个问题,就是照做了之后还是爬不到,返回total=0,这个时候加个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
  • 那么问题来了,要得到网址中的id,但是看我的结果txt,发现爬取的第一个网页是和下面不一样,没有一串数字的,这是因为这是跳转前的网址,我们无法判断得到的网址是否还有一次跳转,所以解决方法是取浏览量之前,取已打开详情页的网址进行分析(已跳转完成的)
respond = requests.get(path)
views = get_views(respond.url)
  • 不同网页完善的信息不同,所以一旦没有获取到需要的内容,程序会死掉哦~怎么解决这个问题呢,就因为这个调试到了今天(所以迟交了作业,抱歉)
    解决方法是要养成每个信息都要判断是否存在的习惯
    突然联系到直播的时候老师有个这样的习惯,在每个获取信息输出之前,会
    判断列表是否为空,像这样:if list else None
 list = [
        '网页分类:'+ url_kind[0].get_text() if url_kind else '网页分类:None',
        '网页标题:'+ title[0].get_text() if title else '网页标题:None',
        '发帖日期:'+ date[0].get_text() if date else '发帖日期:None',
        '店家类型:'+ host_kind,
        '浏览次数:'+ 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',
        '只数:'+ num[0].get_text() if num else '只数:None',
        '位置:'+ pos[0].get_text() if pos else '位置:None'
    ]

我用List存放是为了输出的txt格式好看一点,如果要输出其他的要用字典什么的啦
可以看到个人信息页面很多东西都是None因为他们没有写

  • 个人和商家版的详情页元素位置有轻微区别,这个导致我爬品种的时候,总是会一部份显示防疫的内容,一部分显示品种
    解决办法是判断当前是商家版还是个人版,改变位置,我这里用format(Hkind_judge是主人类型判断...名字奇怪了点哈)
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的信息,要怎么删除呢?(说的就是品种信息)
    删除的方法其实有很多种,我这里用了最粗暴的repla
'宠物种类:'+ kind[0].get_text().replace('\t', '').replace('\n','').replace(' ','') if kind else '宠物种类:None'
  • 挑战自己爬了下需要点击才能显示的电话号码
    然后我发现并不难,因为这个没有用js控制,直接就放在网页源码,所以只要判断好它的位置就可以,要小心的是所有select结果都是列表,没把握需要的信息在哪里的,就先print出来
    这里遇到的问题其实就是有的详情没有给电话,但是得到的列表依然是有一个值的,所以这里不是判断为空,而是判断元素个数是否大于1
'电话:'+ phone[1].get_text() if len(phone) > 1  else '电话:None'
  • 变量名比较混乱抱歉,因为会的单词实在不够多(捂脸),然后也忘了爬价格,不过我觉得价格应该也不难,所以就不管了
    这一次大作业确实发现了很多之前的网页不存在的问题,做起来比较辛苦,但是好有成就感~
    顺便为了保护,每个请求都加了time.sleep(2)保护,但是这个方法速度实在是慢了点
  • 嘛这周的作业也要加油了(づ ̄ 3 ̄)づ
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,348评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,122评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,936评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,427评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,467评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,785评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,931评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,696评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,141评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,483评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,625评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,291评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,892评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,324评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,492评论 2 348

推荐阅读更多精彩内容