一亩三分地论坛

 找回密码
 获取更多干货,去instant注册!

扫码关注一亩三分地公众号
查看: 7627|回复: 9
收起左侧

[DataScience] 手把手教你用python抓网页数据II(scrapy版)

    [复制链接] |试试Instant~ |关注本帖
victorsterling 发表于 2015-6-23 15:51:48 | 显示全部楼层 |阅读模式

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看,没有帐号?获取更多干货,去instant注册!

x
本帖最后由 victorsterling 于 2015-10-28 22:18 编辑

The whole code in github: https://github.com/victorsterling1/news_spider_scrapy

前言:

之前超级玛丽大神写了一个利用python的urllib,urllib2的module去抓取网页数据(链接:手把手教你用python抓网页数据)。这个帖子对我的帮助很大,也让我学习了很多知识。在此,我来好好膜拜一下超级玛丽大神。

作为转专业的学鶸,几个月前难得在北京混了一份技术岗的实习,工作学的算是能熟练一点的技能也就只有爬虫了。有难度的代码都搞得不太懂(没基础的zhazha求不鄙视)。在我码代码的过程中,地里的很多大神跟给我提供了很多的建议和帮助,在此感谢各位大神的帮助,同时在这里也分享一下我自己对于使用pyhton爬虫的一些心得。


就像超级玛丽之前说的,python和网页相关的几个module除了urllib,urllib2,httplib之外,还有mechanize和scrapy等。在这里,我使用的是scrapy去做网络爬虫。

.鐣欏璁哄潧-涓浜-涓夊垎鍦
新手码的代码或许会有很多不尽人意的地方,希望各位大神多多指点,此帖子也仅仅是抛砖引玉,欢迎大家多多讨论。(大神们请尽情喷我代码写的烂吧


步骤一:准备工作
首先要熟悉python的基本知识和使用方法,在这里推荐一门university of Michigan的公开课人人都懂的编程课(Python)。本人今年年初跟的这门课,作为无基础的zhazha,我表示这门课学起来非常简单,毫不费力(估计也是因为这门课是基础中的基础),非常适合转专业的新手去学习。跟完之后对python的基本用法也大致有了了解。
(但是我实际工作中经常会有这种感慨:卧槽!这些代码都是啥?!!我TM真的学过Python吗??

对python有了一定了解后,请安装好pyhton,设置好环境参量,并安装scrapy模块,教程如下:
installation guide. 涓浜-涓夊垎-鍦帮紝鐙鍙戝竷


其它需要的module在实际应用中,就见到需要什么就装什么,反正大多都可以在shell(cmd)中用pip install XX 就可以了。

步骤二:创建自己的项目. From 1point 3acres bbs
scrapy安装完毕之后,就可以开始创建自己的项目了。比如:我们要去做一个从各大新闻网站抓取新闻内容的爬虫。我们就需要从网页中提取标题,正文,日期等信息。

首先,打开cmd,输入scrapy startproject news
就可以创建一个名字为news的项目。一般默认在我的文档目录下生成文件。文件目录如下:
news:.│  scrapy.cfg
│└─news   
   │  items.py    . 鐣欏鐢宠璁哄潧-涓浜╀笁鍒嗗湴
   │  pipelines.py    . 鍥磋鎴戜滑@1point 3 acres
   │  settings.py   
   │  __init__.py   
   │ └─spiders           
             __init__.py
  • scrapy.cfg: 项目配置文件
  • news/: 项目python模块, 呆会代码将从这里导入
  • news/items.py: 项目items文件
  • news/pipelines.py: 项目管道文件
  • news/settings.py: 项目配置文件
  • news/spiders: 放置spider的目录
. more info on 1point3acres.com
步骤三:定义我们要提取的数据(item)
. 涓浜-涓夊垎-鍦帮紝鐙鍙戝竷
Items是将要装载抓取的数据的容器,它工作方式像python里面的字典,但它提供更多的保护,比如对未定义的字段填充以防止拼写错误。
我们使用IDLE(python自带编译器)打开items.py编辑代码,即可完成对item的定义。
  1. from scrapy.item import Item, Field


  2. class NewsItem(Item):
  3.    
  4.     title = Field()
  5.     link = Field()
  6.     content = Field()
  7.     date = Field()
复制代码
步骤四:写爬虫(spider)-google 1point3acres


scrapy给提供的spider有很多种,如:BaseSpider,CrawlSpider,XMLFeedSpider,CSVFeedSpider等等。(关于spider的详细介绍和用法请看这里:手册链接)


其中最简单的是BaseSpider,最常用的是CrawlSpider,在这里我对这俩种进行介绍:


进入spider目录,在这个目录下新建一个py文件,名字就是spider的name,然后进行编辑。

. visit 1point3acres.com for more.
首先是BaseSpider (or Spider):
个人感觉比较适合爬一些有针对性的那种网页,比如:某一个新闻网站某子版块的新闻数据。
下面是一个爬搜狐新闻网站环保版块新闻的例子。
  1. # -*- coding: utf-8 -*-
  2. import scrapy
  3. from news.items import NewsItem
  4. from scrapy.http import Request. Waral 鍗氬鏈夋洿澶氭枃绔,
  5. import requests. Waral 鍗氬鏈夋洿澶氭枃绔,
  6. import re


  7. . Waral 鍗氬鏈夋洿澶氭枃绔,
  8. class SohuSpider(scrapy.Spider):.鏈枃鍘熷垱鑷1point3acres璁哄潧
  9.     name = "sohu"
  10.     allowed_domains = ["gongyi.sohu.com"]
  11.     start_urls = (
  12.                 'http://gongyi.sohu.com/hbdt/',
  13.                 #'http://gongyi.sohu.com/gongyiyw/'
  14.                 #'http://gongyi.sohu.com/salon/index.shtml'
  15.                 #'http://gongyi.sohu.com/focus/index.shtml'
  16.                 #'http://gongyi.sohu.com/gongyicehua/'
  17.         )
  18.     def __init__(self):
  19.         
  20.         self.count = 33.1point3acres缃

  21.     def parse(self, response):
  22.         try:
  23.             lis = response.css('div[class="f14list"]').xpath('ul').xpath('li')
  24.             for li in lis:
  25.                 item = EnvItem()
  26.                 item['link'] = li.xpath('a/@href').extract()[0]
  27.                 if not li.xpath('a/text()'):. from: 1point3acres.com/bbs
  28.                         continue. 鍥磋鎴戜滑@1point 3 acres
  29.                 item['title'] = li.xpath('a/text()').extract()[0]
  30.                 link_info = item['link'].split("/")
  31.                 link_info2 = link_info[-2]
  32.                 item['date'] = link_info2[:4] + '-' + link_info2[4:6] + '-' + link_info2[6:]
  33.                
  34. . From 1point 3acres bbs
  35.                 r = requests.get(item["link"])
  36.                 r.encoding=r.apparent_encoding
  37.                 data = r.text
  38.                 link_list = re.findall('<p>(.*?)</p>' ,data). 1point3acres.com/bbs
  39.                 item["content"] = ''
  40.                 if  link_list:
  41.                     item["content"] = ''.join(link_list)
  42.                 else :
  43.                     print 'NONE'
  44.                 yield item
  45. . Waral 鍗氬鏈夋洿澶氭枃绔,
  46.         except:
  47.             pass

  48. 鏉ユ簮涓浜.涓夊垎鍦拌鍧.
  49.         if self.count>0:
  50.             url = "http://gongyi.sohu.com/hbdt/index_" + str(self.count) + ".shtml"
  51.             print url
  52.             self.count -= 1
  53.             yield Request(url, callback = self.parse)
复制代码
其次是CrawlSpider:
这个就更加粗暴一些,通rule规则去爬此网站域名下所有的网页,再根规则从中选择想要提取数据的网页进行数据提取,(简单粗暴,不过感觉大数据分析抓数据就该这么粗暴地大规模抓数据吧.鏈枃鍘熷垱鑷1point3acres璁哄潧
. 1point3acres.com/bbs
. 鐣欏鐢宠璁哄潧-涓浜╀笁鍒嗗湴
下面是一个爬地方性新闻网站的例子。
  1. #-*-coding:utf-8-*-
  2. #Author: Victor
  3. #Date: 2015-6-18. visit 1point3acres.com for more.
  4. import re
  5. import scrapy
  6. from scrapy.contrib.spiders import CrawlSpider, Rule
  7. from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor.鐣欏璁哄潧-涓浜-涓夊垎鍦
  8. from scrapy.selector import HtmlXPathSelector
  9. from scrapy.http import Request
  10. from scrapy.selector import HtmlXPathSelector. visit 1point3acres.com for more.
  11. import time

  12. from news.items import NewsItem

  13. class HongSpider(CrawlSpider):
  14.     name = 'hong'. from: 1point3acres.com/bbs

  15.     allowed_domains = ['rednet.cn']
  16.     start_urls = ["http://china.rednet.cn/"]
  17.     rules = (
  18.         Rule(SgmlLinkExtractor(allow=(r'http://.*.rednet.cn/[cC]/[0-9]+/[0-9]+/[0-9]+/[0-9]+.htm'), unique=True),callback='parse_item'),
  19.         Rule(SgmlLinkExtractor(allow=(r'http://.*.rednet.cn/[cC].*.*'), unique=True)),. Waral 鍗氬鏈夋洿澶氭枃绔,
  20.         . from: 1point3acres.com/bbs
  21.         )


  22.     def parse_item(self, response):. 1point 3acres 璁哄潧
  23.         try:
  24.             hxs = HtmlXPathSelector(response). 1point3acres.com/bbs
  25.             item = NewsItem()
  26.             item['link'] = response.url
  27.             item['title'] = hxs.select("//head/title/text()").extract()[0].1point3acres缃
  28.             time_raw = item['link'].split('/')
  29.             item['date'] = time_raw[-4] + "-" + time_raw[-3] + "-" + time_raw[-2]
  30.         . 1point3acres.com/bbs
  31.             item['content'] = ''
  32.             content_list = hxs.select("//div[@id='articlecontent']/p/text()").extract()
  33.             if content_list ==[]:
  34.                 content_list = hxs.select("//div[@id='articlecontent']/P/text()").extract()
    . 涓浜-涓夊垎-鍦帮紝鐙鍙戝竷
  35.             if content_list ==[]:
  36.                 content_list = hxs.select("//div[@id='articlecontent']/FONT/text()").extract()
  37.             if content_list ==[]:
  38.                 content_list = hxs.select("//div[@id='articlecontent']/text()").extract()
  39.             if content_list ==[]:
  40.                 content_list = hxs.select("//font[@id='zoom']/text()").extract()
  41.             if content_list ==[]:
  42.                 content_list = hxs.select("//div[@id='zoom']/text()").extract()
  43.             if content_list:
  44.                 item['content'] = ''.join(content_list). From 1point 3acres bbs
  45.             else:. 1point 3acres 璁哄潧
  46.                 print 'None'
  47.             if item['content'] == '':
  48.                 item['content'] = "null"
  49.             yield item
  50.             time.sleep(1)

  51.         except:
  52.             pass
  53.      
复制代码
步骤五:设置存储文件的方式和项目设置


先设置项目的setting:
打开之前的生成的settings.py,编译代码
  1. BOT_NAME = 'news'


  2. SPIDER_MODULES = ['news.spiders']
  3. NEWSPIDER_MODULE = 'news.spiders'-google 1point3acres
  4. ITEM_PIPELINES = [
  5.     'news.pipelines.NewsPipeline']

  6. USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; rv:38.0) Gecko/20100101 Firefox/38.0'
复制代码
其实,前面那几行都已经自动生成好了,我们所需要做的仅仅只是设置一个user_agent而已。这个东西,自己去常用的浏览器找找看能不能看到吧。

虽然我觉得这东西并没有什么卵用······我之前忘记设置了也照样能爬。不过还是严谨一点比较好。

然后是对项目储存方式的设置:
打开之前生成的pipelines.py,进行编译
  1. import json
  2. import codecs
  3. from os import path
  4. from scrapy import signals

  5. class NewsPipeline(object):-google 1point3acres
  6.     def __init__(self):
  7.         self.file = codecs.open('raw_data.json', 'w',"utf-8")
  8.     def process_item(self, item, spider):
  9.         line = json.dumps(dict(item)) + "\n".鐣欏璁哄潧-涓浜-涓夊垎鍦
  10.         self.file.write(line)
  11.         return item
复制代码
将数据保存为json文件,方便之后转换成数据库文件。

当然,如果你想直接需要用,而不是看那些json文件里面看不懂的unicode编码的话,我下面介绍一种可以直接拿出来用的保存方式。
  1. import json
  2. import codecs
  3. from os import path
  4. from scrapy import signals

  5. class NewsPipeline(object):
  6.     def __init__(self):
  7.         self.file = codecs.open('raw_data.doc', 'w','utf-8')
  8.     def process_item(self, item, spider):        
  9.         self.file.write(item['title']+"\n"). from: 1point3acres.com/bbs
  10.         self.file.write(item['link']+"\n")
  11.         self.file.write(item['date']+"\n"). visit 1point3acres.com for more.
  12.         self.file.write(item['content']+"\n")
  13.         return item
  14.         file.close()
复制代码

步骤六:万事俱备,让我们开始爬吧


. 涓浜-涓夊垎-鍦帮紝鐙鍙戝竷
在news文件夹下,按住shift右击,然后选择进入命令窗口,输入:. Waral 鍗氬鏈夋洿澶氭枃绔,
scrapy crawl hong     #hong是我们其中一个spider的name

就可以开始爬啦。

提取数据的文件将保存在当前目录下。
. 涓浜-涓夊垎-鍦帮紝鐙鍙戝竷

欢迎各位大神多多指点我代码上的不足哈。大家多多讨论。












评分

12

查看全部评分

joycevernon 发表于 2015-6-27 15:48:55 | 显示全部楼层
Python不熟但是感觉很有用啊,有空的时候follow介个练习~~谢谢楼主!!
回复 支持 反对

使用道具 举报

 楼主| victorsterling 发表于 2015-6-27 21:07:39 | 显示全部楼层
joycevernon 发表于 2015-6-27 15:48
Python不熟但是感觉很有用啊,有空的时候follow介个练习~~谢谢楼主!!

好嘞,大家互相交流哈!
回复 支持 反对

使用道具 举报

youhusky 发表于 2015-6-27 21:19:18 | 显示全部楼层
Follow 楼主,我也学习
回复 支持 反对

使用道具 举报

xongkoro 发表于 2015-7-3 10:48:09 | 显示全部楼层
谢谢LZ分享。还有一个BeautifulSoup也很好用。
回复 支持 反对

使用道具 举报

pilot_g2 发表于 2015-7-8 15:05:30 | 显示全部楼层
谢谢楼主分享,学习了!
回复 支持 反对

使用道具 举报

 楼主| victorsterling 发表于 2015-7-8 17:37:33 | 显示全部楼层
xongkoro 发表于 2015-7-3 10:48
谢谢LZ分享。还有一个BeautifulSoup也很好用。
. 鍥磋鎴戜滑@1point 3 acres
最近用了一下beautifulsoup,感觉这个跟scrapy相比还是差很多啊,很难实现一些html节点的精准抓取,只是一些常用的,笼统的数据提取,感觉不是很有效力。还是说我自己的用的不地道??
回复 支持 反对

使用道具 举报

calalia 发表于 2015-7-21 09:51:02 | 显示全部楼层
强力马可马可马可!!!!!!!!!
回复 支持 反对

使用道具 举报

 楼主| victorsterling 发表于 2015-10-28 22:20:33 | 显示全部楼层
已把整体的code上传到github上,大家想要实践的话,可以直接下载下来试试看。
回复 支持 反对

使用道具 举报

本版积分规则

请点这里访问我们的新网站:一亩三分地Instant.

Instant搜索更强大,不扣积分,内容组织的更好更整洁!目前仍在beta版本,努力完善中!反馈请点这里

关闭

一亩三分地推荐上一条 /5 下一条

手机版|小黑屋|一亩三分地论坛声明 ( 沪ICP备11015994号 )

custom counter

GMT+8, 2016-12-11 22:25

Powered by Discuz! X3

© 2001-2013 Comsenz Inc. Design By HUXTeam

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