鱼C论坛

 找回密码
 立即注册
查看: 2018|回复: 3

[已解决]python 爬虫数据重复

[复制链接]
发表于 2017-4-6 21:30:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. import scrapy
  2. import re

  3. # CMD 运行
  4. # scrapy runspider cnblog_spider.py -o cnblog.csv   

  5. class CnblogSpider(scrapy.Spider):
  6.     name='cnblog'
  7.     allowed_domains = ['https://www.cnblogs.com/']
  8.     start_urls=['http://www.cnblogs.com/pick/#p%s'% id for id in range(1,21)]
  9.    
  10.     def parse(self,response):
  11.         allblog= response.xpath('//div[@class="post_item"]')
  12.         for each in allblog:
  13.             dignum=int(each.xpath('div[@class="digg"]/div/span/text()')[0].extract())
  14.             titlename=each.xpath('div[@class="post_item_body"]/h3/a/text()')[0].extract()
  15.             content=each.xpath('div[@class="post_item_body"]/p/text()')[0].extract().replace(r'\r','').replace(r'\n','').strip()
  16.             postname=each.xpath('div[@class="post_item_body"]/div/a/text()')[0].extract()
  17.             comment=each.xpath('div[@class="post_item_body"]/div/span[1]/a/text()')[0].extract().strip()
  18.             p1=r'评论\((\d+)\)'
  19.             comnum=int(re.findall(p1,comment)[0])
  20.             view=each.xpath('div[@class="post_item_body"]/div/span[2]/a/text()')[0].extract().strip()
  21.             p2=r'阅读\((\d+)\)'
  22.             viewnum=int(re.findall(p2,view)[0])
  23.             yield {'标题':titlename,发布者':postname,'点赞数':dignum,'评论数':comnum,'浏览数':viewnum,'内容':content}   
复制代码


为啥爬出来 数据会重复-----不能按url规则索引
最佳答案
2017-4-7 11:34:18
先说结果:你这个问题的原因我已经找到了,但是如何在scrapy中解决这个问题,我还没有完成。

下面简单说下过程:
首先我在scrapy下面发现,虽然start_urls被传送进去,但立刻就会给Dupefilter给过滤掉,我天真的以为Dupefilter可能因为网页的原因出现了一些不明故障,手动关掉之后,却又发现scrapy.core.engine和scrapy.core.scraper页面居然不同,scrapy.core.scraper始终固定在http://www.cnblogs.com/pick/ 上。由此,我开始怀疑这个网页url本身有问题。

我通过requests对你提供的网页进行链接,代码如下:
  1. r = requests.get('http://www.cnblogs.com/pick/#p1')
  2. print(r.text)
  3. r = requests.get('http://www.cnblogs.com/pick/#p2')
  4. print('===========================================')
  5. print(r.text)
复制代码

通过对比两次连接的结果后发现,http://www.cnblogs.com/pick/#p2 本身并不是真正链接。
最后通过F12发现,实际上,文章部分是给包装在一个Postlist.aspx里面的。于是传入参数有如下代码:
  1. import requests

  2. payload = {'CategoryType': "Picked", 'ParentCategoryId': 0, 'CategoryId': -2, 'PageIndex': 1, 'TotalPostCount': 1554}
  3. r = requests.get('http://www.cnblogs.com/pick/#p1', params=payload)
  4. print(r.text)
  5. payload = {'CategoryType': "Picked", 'ParentCategoryId': 0, 'CategoryId': -2, 'PageIndex': 2, 'TotalPostCount': 1554}
  6. r = requests.get('http://www.cnblogs.com/pick/#p2', params=payload)
  7. print('===========================================')
  8. print(r.text)
复制代码

对比后发现,这次得到的两个页面内容就不相同了,于是可以确定的是PageIndex这个参数才是确定页面的关键。

最后:
其实根据以上内容,相信你也可以明白,只要能够把上面payload部分的内容,通过scrapy参数传入就可以了。
但是我对scrapy确实不太熟,而我觉得scrapy又太过复杂,解决一个小的而又不常见问题需要去研究整个scrapy运行的机制,所以短期内也不会去研究这问题应该怎么处理。所以这只能留给你自己去解决了。如果你有了结论,希望你也能告知。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-4-7 11:34:18 | 显示全部楼层    本楼为最佳答案   
先说结果:你这个问题的原因我已经找到了,但是如何在scrapy中解决这个问题,我还没有完成。

下面简单说下过程:
首先我在scrapy下面发现,虽然start_urls被传送进去,但立刻就会给Dupefilter给过滤掉,我天真的以为Dupefilter可能因为网页的原因出现了一些不明故障,手动关掉之后,却又发现scrapy.core.engine和scrapy.core.scraper页面居然不同,scrapy.core.scraper始终固定在http://www.cnblogs.com/pick/ 上。由此,我开始怀疑这个网页url本身有问题。

我通过requests对你提供的网页进行链接,代码如下:
  1. r = requests.get('http://www.cnblogs.com/pick/#p1')
  2. print(r.text)
  3. r = requests.get('http://www.cnblogs.com/pick/#p2')
  4. print('===========================================')
  5. print(r.text)
复制代码

通过对比两次连接的结果后发现,http://www.cnblogs.com/pick/#p2 本身并不是真正链接。
最后通过F12发现,实际上,文章部分是给包装在一个Postlist.aspx里面的。于是传入参数有如下代码:
  1. import requests

  2. payload = {'CategoryType': "Picked", 'ParentCategoryId': 0, 'CategoryId': -2, 'PageIndex': 1, 'TotalPostCount': 1554}
  3. r = requests.get('http://www.cnblogs.com/pick/#p1', params=payload)
  4. print(r.text)
  5. payload = {'CategoryType': "Picked", 'ParentCategoryId': 0, 'CategoryId': -2, 'PageIndex': 2, 'TotalPostCount': 1554}
  6. r = requests.get('http://www.cnblogs.com/pick/#p2', params=payload)
  7. print('===========================================')
  8. print(r.text)
复制代码

对比后发现,这次得到的两个页面内容就不相同了,于是可以确定的是PageIndex这个参数才是确定页面的关键。

最后:
其实根据以上内容,相信你也可以明白,只要能够把上面payload部分的内容,通过scrapy参数传入就可以了。
但是我对scrapy确实不太熟,而我觉得scrapy又太过复杂,解决一个小的而又不常见问题需要去研究整个scrapy运行的机制,所以短期内也不会去研究这问题应该怎么处理。所以这只能留给你自己去解决了。如果你有了结论,希望你也能告知。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-4-9 21:43:25 | 显示全部楼层
ooxx7788 发表于 2017-4-7 11:34
先说结果:你这个问题的原因我已经找到了,但是如何在scrapy中解决这个问题,我还没有完成。

下面简单说 ...

可以QQ咨询吗 谢谢了 有点地方不懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-4-10 15:21:10 | 显示全部楼层
本帖最后由 Hoo_gang 于 2017-4-10 15:22 编辑
ooxx7788 发表于 2017-4-7 11:34
先说结果:你这个问题的原因我已经找到了,但是如何在scrapy中解决这个问题,我还没有完成。

下面简单说 ...


https://www.cnblogs.com/pick/p#78

以第78页为例,其实点击页面下方的翻页脚本检查元素,发现,网页的真实链接是https://www.cnblogs.com/pick/78/

也就是两种方式都可以get到内容,具体到如果按你的回答传递参数,目前我还不知道在scrapy怎么传入post是payload的参数,百度只找到传递headers和formdata,只能用真实链接https://www.cnblogs.com/pick/78/ 来爬取数据
  1. import requests


  2. payload = {'CategoryType': "Picked", 'ParentCategoryId': 0, 'CategoryId': -2, 'PageIndex': 3, 'TotalPostCount': 1554}
  3. r = requests.post('https://www.cnblogs.com/mvc/AggSite/PostList.aspx', params=payload)
  4. print(r.text)

  5. import requests

  6. r=requests.get('https://www.cnblogs.com/pick/2/')
  7. print(r.text)
复制代码




现在的代码调整为:
  1. import scrapy
  2. import re

  3. # CMD 运行
  4. # scrapy runspider cnblog_spider.py -o cnblog.csv   

  5. class CnblogSpider(scrapy.Spider):
  6.     name='cnblog'
  7.     allowed_domains = ['https://www.cnblogs.com/']
  8.     start_urls=['https://www.cnblogs.com/pick/%s/'% i for i in range(1,78)]
  9.    
  10.    
  11.     def parse(self,response):
  12.         allblog=response.xpath('//div[@class="post_item"]')
  13.         for each in  allblog:
  14.             dignum=int(each.xpath('div[@class="digg"]/div/span/text()').extract()[0])
  15.             titlename=each.xpath('div[@class="post_item_body"]/h3/a/text()').extract()[0]
  16.             content=each.xpath('div[@class="post_item_body"]/p').xpath('string(.)').extract()[0].replace('\r','').replace('\n','').replace('.','').strip()
  17.             postname=each.xpath('div[@class="post_item_body"]/div/a/text()').extract()[0].strip()
  18.             comment=each.xpath('div[@class="post_item_body"]/div/span[1]/a/text()').extract()[0].strip()
  19.             p1=r'评论\((\d+)\)'
  20.             comnum=int(re.findall(p1,comment)[0])
  21.             view=each.xpath('div[@class="post_item_body"]/div/span[2]/a/text()').extract()[0].strip()
  22.             p2=r'阅读\((\d+)\)'
  23.             viewnum=int(re.findall(p2,view)[0])
  24.             yield {'标题':titlename,'发布者':postname,'点赞数':dignum,'评论数':comnum,'浏览数':viewnum,'内容':content}   
复制代码



可以爬取所有数据,不过从这个实例,发现地址栏显示的url并非真实get数据的url,需要查看检查元素,防止进入陷阱。

对你给予的帮助和提示,表示感谢。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-20 00:41

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表