python利用xpath爬取网上数据并存储到django模型中
帮朋友制作一个网站,需要一些产品数据信息,因为是代理其他公司产品,直接爬取代理公司产品数据
1.设计数据库
fromdjango.dbimportmodels
fromuuslugimportslugify
importuuid
importos
defproducts_directory_path(instance,filename):
ext=filename.split('.')[-1]
filename='{}.{}'.format(uuid.uuid4().hex[:8],ext)
#returnthewholepathtothefile
returnos.path.join('images',"products",instance.title,filename)
defproduct_relatedimage_directory_path(instance,filename):
ext=filename.split('.')[-1]
filename='{}.{}'.format(uuid.uuid4().hex[:8],ext)
#returnthewholepathtothefile
returnos.path.join('images',"product_relatedimage",instance.product.title,filename)
classProductsCategory(models.Model):
"""产品分类"""
name=models.CharField('产品分类名',max_length=80,unique=True)
description=models.TextField('产品分类描述',blank=True,null=True)
slug=models.SlugField('slug',max_length=80,blank=True,null=True)
parent_category=models.ForeignKey('self',verbose_name="父级分类",blank=True,null=True,on_delete=models.CASCADE)
defsave(self,*args,**kwargs):
ifnotself.idornotself.slug:
self.slug=slugify(self.name)
super().save(*args,**kwargs)
def__str__(self):
returnself.name
classMeta:
ordering=['name']
verbose_name="产品分类"
verbose_name_plural=verbose_name
classProductsTag(models.Model):
"""产品标签"""
name=models.CharField('产品标签名',max_length=30,unique=True)
slug=models.SlugField('slug',max_length=40)
def__str__(self):
returnself.name
defsave(self,*args,**kwargs):
ifnotself.idornotself.slug:
self.slug=slugify(self.name)
super().save(*args,**kwargs)
classMeta:
ordering=['name']
verbose_name="产品标签"
verbose_name_plural=verbose_name
classProduct(models.Model):
title=models.CharField('标题',max_length=255,unique=True)
slug=models.SlugField('slug',max_length=255,blank=True,null=True)
jscs=models.TextField('技术参数',blank=True,null=True)
image=models.ImageField(upload_to=products_directory_path,verbose_name="产品图片")
views=models.PositiveIntegerField('浏览量',default=0)
category=models.ForeignKey('ProductsCategory',verbose_name='分类',on_delete=models.CASCADE,blank=True,null=True)
tags=models.ManyToManyField('ProductsTag',verbose_name='标签集合',blank=True)
defsave(self,*args,**kwargs):
ifnotself.idornotself.slug:
self.slug=slugify(self.title)
super().save(*args,**kwargs)
defupdate_views(self):
self.views+=1
self.save(update_fields=['views'])
defget_pre(self):
returnProduct.objects.filter(id__lt=self.id).order_by('-id').first()
defget_next(self):
returnProduct.objects.filter(id__gt=self.id).order_by('id').first()
def__str__(self):
returnself.title
classMeta:
verbose_name="产品"
verbose_name_plural=verbose_name
classProductAdvantage(models.Model):
content=models.TextField('产品优势',blank=True,null=True)
product=models.ForeignKey(Product,on_delete=models.CASCADE,blank=True,null=True)
def__str__(self):
returnself.content
classMeta:
verbose_name="产品优势"
verbose_name_plural=verbose_name
classProductBody(models.Model):
body=models.CharField('产品内容',max_length=256,blank=True,null=True)
product=models.ForeignKey(Product,on_delete=models.CASCADE,blank=True,null=True)
def__str__(self):
returnself.product.title
classMeta:
verbose_name="产品内容"
verbose_name_plural=verbose_name
2.脚本编写
2.1编写获取网页源代码函数
defget_one_page(url):
try:
headers={
"User-Agent":"Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/51.0.2704.103Safari/537.36"}
res=requests.get(url=url,headers=headers)
res.encoding='utf-8'
ifres.status_code==200:
returnres.text
else:
returnNone
exceptException:
returnNone
2.2根据base页面获取所有产品分类页面链接
if__name__=='__main__':
content=get_one_page(url)
tree=etree.HTML(content)
#产品分类url
catgory_urls=tree.xpath('//div[@class="fdh-01-nav"]/div/h3/a/@href')
#处理catgory_urls
forurlincatgory_urls:
url='http://www.kexinjianji.com'+url
print(url)
2.3根据产品分类页面链接获取对应所有产品链接
if__name__=='__main__':
content=get_one_page(url)
tree=etree.HTML(content)
#产品分类
catgory=tree.xpath('//div[@class="cplb-3n-ts-03b"]/h3/span/text()')
print("产品分类:"+catgory[0])
#该分类下产品url
urls=tree.xpath('//div[@class="cplb-3n-ts-03-list"]/dl/dt/a/@href')
#处理url
forurlinurls:
url='http://www.kexinjianji.com'+url
print(url)
print("=====================================================")
两者结合起来就可以打印出所有产品链接
if__name__=='__main__':
content=get_one_page(url)
tree=etree.HTML(content)
#产品分类url
catgory_urls=tree.xpath('//div[@class="fdh-01-nav"]/div/h3/a/@href')
#处理catgory_urls
forurlincatgory_urls:
url='http://www.kexinjianji.com'+url
content=get_one_page(url)
tree=etree.HTML(content)
#产品分类
catgory=tree.xpath('//div[@class="cplb-3n-ts-03b"]/h3/span/text()')
print("产品分类:"+catgory[0])
#该分类下产品url
urls=tree.xpath('//div[@class="cplb-3n-ts-03-list"]/dl/dt/a/@href')
#处理url
forurlinurls:
url='http://www.kexinjianji.com'+url
print(url)
print("=====================================================")
2.2使用xpath解析函数返回产品链接的内容
if__name__=='__main__':
content=get_one_page(url)
tree=etree.HTML(content)
#产品名称
title=tree.xpath('//*[@id="wrap"]//h1/text()')
images=tree.xpath('//div[@class="sol_tj_left"]/a/img/@src')
#产品图片
images_url='http://www.kexinjianji.com/'+images[0]
#性能特点
xntd=tree.xpath('//div[@class="w"]//div/span/text()|//div[@class="w"]//div/text()')
#技术参数
jscs=tree.xpath('//table')[0]
jscs_str=etree.tostring(jscs,encoding='utf-8').decode('utf-8')
#产品内容
cpnr=tree.xpath('//div[@class="describe"]/p')
print('产品名称:'+title[0])
print('产品图片:'+images_url)
fortdinxntd:
print('性能特点:'+td)
print('技术参数:'+jscs_str)
forcpincpnr:
#string(.)获取当前标签下所有文本内容
cp=cp.xpath('string(.)')
print('产品内容:'+cp)
print('============================================')
将三者结合在一起就可以获取所有产品信息
if__name__=='__main__':
content=get_one_page(url)
tree=etree.HTML(content)
#产品分类url
catgory_urls=tree.xpath('//div[@class="fdh-01-nav"]/div/h3/a/@href')
#处理catgory_urls
forurlincatgory_urls:
url='http://www.kexinjianji.com'+url
content=get_one_page(url)
tree=etree.HTML(content)
#产品分类
catgory=tree.xpath('//div[@class="cplb-3n-ts-03b"]/h3/span/text()')
#该分类下产品url
urls=tree.xpath('//div[@class="cplb-3n-ts-03-list"]/dl/dt/a/@href')
#处理url
forurlinurls:
url='http://www.kexinjianji.com'+url
content=get_one_page(url)
try:
tree=etree.HTML(content)
#产品名称
title=tree.xpath('//*[@id="wrap"]//h1/text()')
images=tree.xpath('//div[@class="sol_tj_left"]/a/img/@src')
#产品图片
images_url='http://www.kexinjianji.com'+images[0]
#性能特点
xntd=tree.xpath('//div[@class="w"]//div/span/text()|//div[@class="w"]//div/text()')
#技术参数
jscs=tree.xpath('//table')[0]
jscs_str=etree.tostring(jscs,encoding='utf-8').decode('utf-8')
#产品内容
cpnr=tree.xpath('//div[@class="describe"]/p')
print("产品分类:"+catgory[0])
print('产品链接:'+url)
print('产品名称:'+title[0])
print('产品图片:'+images_url)
fortdinxntd:
print('性能特点:'+td.strip())
#print('技术参数:'+jscs_str)
forcpincpnr:
#string(.)获取当前标签下所有文本内容
cp=cp.xpath('string(.)')
print('产品内容:'+cp)
print('============================================')
exceptExceptionase:
print(e)
print('出错url:'+url)
pass
3.存储到django模型
importrequests
fromlxml.htmlimportetree
importos
importdjango
importuuid
fromdjango.core.files.baseimportContentFile
os.environ.setdefault("DJANGO_SETTINGS_MODULE","jiaobanzhan.settings")
django.setup()
fromproducts.modelsimportProductBody,ProductsCategory,Product,ProductAdvantage
url='http://www.kexinjianji.com/product/hzshntjbz_1/'
defget_one_page(url):
try:
headers={
"User-Agent":"Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/51.0.2704.103Safari/537.36"}
res=requests.get(url=url,headers=headers,timeout=10)
res.encoding='utf-8'
ifres.status_code==200:
returnres.text
else:
returnNone
exceptException:
print('aa')
returnNone
if__name__=='__main__':
content=get_one_page(url)
tree=etree.HTML(content)
#产品分类url
catgory_urls=tree.xpath('//div[@class="fdh-01-nav"]/div/h3/a/@href')
#处理catgory_urls
forurlincatgory_urls:
url='http://www.kexinjianji.com'+url
content=get_one_page(url)
tree=etree.HTML(content)
#产品分类
p_catgory=tree.xpath('//div[@class="cplb-3n-ts-03b"]/h3/span/text()')
#该分类下产品url
urls=tree.xpath('//div[@class="cplb-3n-ts-03-list"]/dl/dt/a/@href')
#处理url
forurlinurls:
url='http://www.kexinjianji.com'+url
content=get_one_page(url)
try:
tree=etree.HTML(content)
#产品名称
title=tree.xpath('//*[@id="wrap"]//h1/text()')
images=tree.xpath('//div[@class="sol_tj_left"]/a/img/@src')
#产品图片
images_url='http://www.kexinjianji.com'+images[0]
#性能特点
xntd=tree.xpath('//div[@class="w"]//div/span/text()|//div[@class="w"]//div/text()')
#技术参数
jscs=tree.xpath('//table')[0]
jscs_str=etree.tostring(jscs,encoding='utf-8').decode('utf-8')
#产品内容
cpnr=tree.xpath('//div[@class="describe"]/p')
#判断是否有这分类,没有则新建
catgory=p_catgory[0]
products_catgory=ProductsCategory.objects.filter(name=catgory).exists()
ifproducts_catgory:
products_catgory=ProductsCategory.objects.get(name=catgory)
else:
products_catgory=ProductsCategory(name=catgory)
products_catgory.save()
print(products_catgory)
#保存产品图片
image_content=requests.get(url=images_url)
ext=images_url.split('.')[-1]#获取图片类型
filename='{}.{}'.format(uuid.uuid4().hex[:8],ext)#随机生成图片名字
upload_image_file=ContentFile(image_content.content,name=filename)#将图片保存为django类型
product=Product(title=title[0],jscs=jscs_str,image=upload_image_file,category=products_catgory)
product.save()
fortdinxntd:
product_advantage=ProductAdvantage()
product_advantage.content=td
product_advantage.product=product
product_advantage.save()
forcpincpnr:
cp=cp.xpath('string(.)')
product_body=ProductBody()
product_body.body=cp
product_body.product=product
product_body.save()
exceptExceptionase:
print(e)
print('出错url:'+url)
最后自己手动处理出错url(页面没有获取到技术参数,技术参数是一张图片)
4.总结
1.xpath获取标签内容时,p标签中嵌套span标签,源码如下
板宽:1500mm
板厚:4.5mm
出料口:6口
重量:6000kg
使用xpath获取p标签内容
我想得到的效果如下
板宽:1500mm
板厚:4.5mm
出料口:6口
重量:6000kg
使用以下xpath只能分开获取,不是想要的效果
//div[@class="describe"]/p/span/text()|//div[@class="describe"]/p/text()
百度之后找到的解决办法,使用xpath(‘string(.)')
1.先获取所有p标签
cpnr=tree.xpath('//div[@class="describe"]/p')
2.使用**string(.)**获取所有标签所有文本
cp=cp.xpath('string(.)')
循环遍历所有p标签即可
到此这篇关于python利用xpath爬取网上数据并存储到django模型中的文章就介绍到这了,更多相关xpath爬取网上数据存储到django模型内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。