菜鸟爬取中关村手机详情页参数及报价

菜鸟爬取中关村手机详情页参数及报价

背景介绍:

  • 需求是爬取所有手机详情页各个手机型号对应的价位区间及参数;
  • 此前没有爬虫经历,套用网上教程屡屡报错,痛定思痛决定自己搜索爬虫框架,参照官方文档并整理网页源码规则,制定适合自己的爬取方案;
  • 网上的爬虫框架有scrapy和bs4,个人觉得bs4较易上手,也能满足本次爬取需求,所以选择了bs4;
  • 感兴趣的筒子可以研究下scrapy哦,貌似递归爬取很强大的赶脚;
  • 废话不多说,下面开始爬取吧~

方案很简单,主要分三步:

  • 观察列表页和详情页之间的关系后发现,列表页中 /cell_phone/index375437.shtml 的数字对应详情页url中的数字,由此联想到,可以把这个数字抠出来作为商品id,放入详情页url中,由此获取详情页链接 http://detail.zol.com.cn/cell_phone/index375437.shtml
  • 列表页
  • 详情页
  • 详情页1
  • 结果数据:
  • 结果数据
  • 第一步,爬取列表页所有的商品id(观察网页后发现,前104页包含了所有有效商品id,104页之后均为空,可以写for循环获取前104页的所有商品id);
  • 第二步,将所有商品id带入详情页url获取所有详情页链接 ;
  • 第三步,同样循环获取所有详情页源代码,并解析出需要的字段存到csv上。
    备注:当然啦,中间涉及要一些调试和解析的过程,是比较费神的,好在都已经解决。
    这里获取的详情字段为16个(标题、手机大类名(比如中兴)、中文名称、别名(含英文名称)、上市时间、屏幕尺寸、商家指导价、价格区间、运行内存、存储内存、内核、主屏幕、前置摄像头、后置摄像头、电容、电池类型)+1个(详情页url,方便对照):

参考网址

下面就奉上爬取代码啦!为了方便测试,最后还有爬取其中一个网页的测试代码哦~
建议对照网页源码,更易于理解解析过程。参考网址:
https://www.crummy.com/software/BeautifulSoup/bs3/documentation.zh.html
http://www.jb51.net/article/99453.htm

爬取代码

#--------------------以此为准:爬取zol手机详情页参数,价格等信息
#----------------------------爬取列表页url并解出商品id
 #-*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
#a=soup.get_text().encode('utf-8')
import requests
from bs4 import BeautifulSoup
import numpy as np
import urllib
import urllib2
import re
import os
from bs4 import BeautifulSoup
import pandas as pd
os.chdir('/Users/wyy/Downloads/')
print(os.getcwd())
if __name__=='__main__':
    all_pkg=[]
    for i in range(1,104):
        url='http://detail.zol.com.cn/cell_phone_index/subcate57_0_list_1_0_9_2_0_'+str(i)+'.html'
        headers={
  'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.7 (KHTML, like Gecko) Version/9.1.2 Safari/601.7.7'}#防止反爬
        request=urllib2.Request(url=url,headers=headers)
        response=urllib2.urlopen(request)
        content= response.read()
        soup=BeautifulSoup(content,"lxml")
        lt=soup.findAll(["a","href"])
        for j in lt:
            pkg_en=j.get('href')
           # pkg=pkg_en.split('/')[-1]
            pair=[pkg_en]
            all_pkg.append(pair)
            all_pkg1=pd.DataFrame(all_pkg)

#/Users/wyy/Downloads
all_pkg1.columns=['url1']
t1=all_pkg1.dropna(axis=0,how='any',thresh=None,subset=None,inplace=False)
# axis 指 轴,0是行,1是列,
# how 是删除条件:any 任意一个为na则删除整行/列,all 整行/列为na才删除
# inplace 是否在原DataFrame 上进行删除,false为否
t2=t1.loc[(t1['url1'].str.contains('/cell_phone/index'))]#筛选出有用的url1
t3=t2.drop_duplicates()#有效url去重后有4913行(个商品id)
# 怎样删除list中空字符?
# 最简单的方法:new_list = [ x for x in li if x != '' ]
#t3.to_csv('phone_url.csv',encoding='utf-8')#处理成手机id(phone_url.csv)
#去空格
# s = ' rtrt3434'
# s.strip()
#--------------------------------------------获取详情数据

#将手机id传入介绍首页获取详情介绍信息
 #-*- coding: utf-8 -*-
def map1(x):
    t=str(x.url1)
    s=re.findall(r"x(.+?).shtml",t)#正则
    return s[0]#取出list中第一个元素
t3['url2']=t3.apply(lambda x:map1(x),1)#1是对行操作,默认对列操作
t3.head()
# Out[23]:
#    Unnamed: 0                            url1     url2
# 0          35  /cell_phone/index1164015.shtml  1164015
# 1          36   /cell_phone/index375437.shtml   375437
# 2          37  /cell_phone/index1164296.shtml  1164296
# 3          38  /cell_phone/index1175015.shtml  1175015
# 4          39  /cell_phone/index1158842.shtml  1158842
#t4=pd.read_csv('phone_id.csv')
#if __name__=='__main__':
pag=[]
data = []
for i in t3['url2']:
    url='http://detail.zol.com.cn/cell_phone/index'+str(i)+'.shtml'
    headers={
  'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.7 (KHTML, like Gecko) Version/9.1.2 Safari/601.7.7'}
    request=urllib2.Request(url=url,headers=headers)
    response=urllib2.urlopen(request)
    content= response.read()
    soup=[url,BeautifulSoup(content,"lxml")]
    pag.append(soup)
    pag1= pd.DataFrame(pag,columns=['url','pag'])
    #pag1.to_csv('phone_zol_origin.csv',encoding='utf-8')
for j in pag:
    try:
        Name=[x.split('=')[1].strip() for x in j[1].findAll(text=re.compile("manuName"))[0].split(';') if re.findall('manuName',x)][0][1:-1]#最后一个0表示取出list中的元素,strip()去空格,[1:-1]去掉引号,大类名-中兴
    except:
        Name = ''
    try:
       showdate=[x for x in j[1].find_all("span",{
  "class":"showdate"})[0]][0]#上市时间
    except:
       showdate = ''
    try<
  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值