一亩三分地论坛

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

一亩三分地官方iOS手机应用下载
查看: 8792|回复: 9
收起左侧

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

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

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

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

x
本帖最后由 victorsterling 于 2015-10-28 22:18 编辑
. 1point 3acres 璁哄潧
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去做网络爬虫。


新手码的代码或许会有很多不尽人意的地方,希望各位大神多多指点,此帖子也仅仅是抛砖引玉,欢迎大家多多讨论。(大神们请尽情喷我代码写的烂吧. 1point3acres.com/bbs


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

对python有了一定了解后,请安装好pyhton,设置好环境参量,并安装scrapy模块,教程如下:. 鐣欏鐢宠璁哄潧-涓浜╀笁鍒嗗湴
installation guide

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

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

首先,打开cmd,输入scrapy startproject news. 鐗涗汉浜戦泦,涓浜╀笁鍒嗗湴
就可以创建一个名字为news的项目。一般默认在我的文档目录下生成文件。文件目录如下:
news:.│  scrapy.cfg
│└─news   
   │  items.py   
   │  pipelines.py   
   │  settings.py   
   │  __init__.py    . visit 1point3acres.com for more.
   │ └─spiders           -google 1point3acres
             __init__.py
  • scrapy.cfg: 项目配置文件
  • news/: 项目python模块, 呆会代码将从这里导入
  • news/items.py: 项目items文件
  • news/pipelines.py: 项目管道文件
  • news/settings.py: 项目配置文件
  • news/spiders: 放置spider的目录. 涓浜-涓夊垎-鍦帮紝鐙鍙戝竷

步骤三:定义我们要提取的数据(item)

Items是将要装载抓取的数据的容器,它工作方式像python里面的字典,但它提供更多的保护,比如对未定义的字段填充以防止拼写错误。
我们使用IDLE(python自带编译器)打开items.py编辑代码,即可完成对item的定义。
  1. from scrapy.item import Item, Field


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


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


其中最简单的是BaseSpider,最常用的是CrawlSpider,在这里我对这俩种进行介绍:
.鏈枃鍘熷垱鑷1point3acres璁哄潧

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


首先是BaseSpider (or Spider):
个人感觉比较适合爬一些有针对性的那种网页,比如:某一个新闻网站某子版块的新闻数据。. 1point3acres.com/bbs
下面是一个爬搜狐新闻网站环保版块新闻的例子。
  1. # -*- coding: utf-8 -*-
  2. import scrapy. 鍥磋鎴戜滑@1point 3 acres
  3. from news.items import NewsItem. 鍥磋鎴戜滑@1point 3 acres
  4. from scrapy.http import Request
  5. import requests
  6. import re 鏉ユ簮涓浜.涓夊垎鍦拌鍧.


  7. class SohuSpider(scrapy.Spider):
  8.     name = "sohu"
  9.     allowed_domains = ["gongyi.sohu.com"]
  10.     start_urls = (
  11.                 'http://gongyi.sohu.com/hbdt/',
  12.                 #'http://gongyi.sohu.com/gongyiyw/'. more info on 1point3acres.com
  13.                 #'http://gongyi.sohu.com/salon/index.shtml'
  14.                 #'http://gongyi.sohu.com/focus/index.shtml'.鏈枃鍘熷垱鑷1point3acres璁哄潧
  15.                 #'http://gongyi.sohu.com/gongyicehua/'
  16.         )-google 1point3acres
  17.     def __init__(self):. From 1point 3acres bbs
  18.         
  19.         self.count = 33
  20. . visit 1point3acres.com for more.
  21.     def parse(self, response):. visit 1point3acres.com for more.
  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()'):
  28.                         continue
  29.                 item['title'] = li.xpath('a/text()').extract()[0]. 1point 3acres 璁哄潧
  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.                 r = requests.get(item["link"])
  35.                 r.encoding=r.apparent_encoding
  36.                 data = r.text
  37.                 link_list = re.findall('<p>(.*?)</p>' ,data)
  38.                 item["content"] = ''
  39.                 if  link_list:
  40.                     item["content"] = ''.join(link_list)
  41.                 else :
  42.                     print 'NONE'
  43.                 yield item

  44.         except:. Waral 鍗氬鏈夋洿澶氭枃绔,
  45.             pass. from: 1point3acres.com/bbs


  46. .1point3acres缃
  47.         if self.count>0:
  48.             url = "http://gongyi.sohu.com/hbdt/index_" + str(self.count) + ".shtml"
  49.             print url
  50.             self.count -= 1
  51.             yield Request(url, callback = self.parse)
复制代码
其次是CrawlSpider:. from: 1point3acres.com/bbs
这个就更加粗暴一些,通rule规则去爬此网站域名下所有的网页,再根规则从中选择想要提取数据的网页进行数据提取,(简单粗暴,不过感觉大数据分析抓数据就该这么粗暴地大规模抓数据吧


下面是一个爬地方性新闻网站的例子。
  1. #-*-coding:utf-8-*-
  2. #Author: Victor
  3. #Date: 2015-6-18
  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
  11. import time
  12. . 涓浜-涓夊垎-鍦帮紝鐙鍙戝竷
  13. from news.items import NewsItem

  14. class HongSpider(CrawlSpider):
  15.     name = 'hong'

  16.     allowed_domains = ['rednet.cn']
  17.     start_urls = ["http://china.rednet.cn/"].1point3acres缃
  18.     rules = (
  19.         Rule(SgmlLinkExtractor(allow=(r'http://.*.rednet.cn/[cC]/[0-9]+/[0-9]+/[0-9]+/[0-9]+.htm'), unique=True),callback='parse_item'),
  20.         Rule(SgmlLinkExtractor(allow=(r'http://.*.rednet.cn/[cC].*.*'), unique=True)),
  21.         
  22.         ). 鍥磋鎴戜滑@1point 3 acres


  23.     def parse_item(self, response):
  24.         try:
  25.             hxs = HtmlXPathSelector(response). visit 1point3acres.com for more.
  26.             item = NewsItem()
  27.             item['link'] = response.url 鏉ユ簮涓浜.涓夊垎鍦拌鍧.
  28.             item['title'] = hxs.select("//head/title/text()").extract()[0]
  29.             time_raw = item['link'].split('/')
  30.             item['date'] = time_raw[-4] + "-" + time_raw[-3] + "-" + time_raw[-2]
  31.         
  32.             item['content'] = ''
  33.             content_list = hxs.select("//div[@id='articlecontent']/p/text()").extract()
  34.             if content_list ==[]:
  35.                 content_list = hxs.select("//div[@id='articlecontent']/P/text()").extract()
  36.             if content_list ==[]:
  37.                 content_list = hxs.select("//div[@id='articlecontent']/FONT/text()").extract()
  38.             if content_list ==[]:
  39.                 content_list = hxs.select("//div[@id='articlecontent']/text()").extract()
  40.             if content_list ==[]:
  41.                 content_list = hxs.select("//font[@id='zoom']/text()").extract(). from: 1point3acres.com/bbs
  42.             if content_list ==[]:
  43.                 content_list = hxs.select("//div[@id='zoom']/text()").extract()
  44.             if content_list:-google 1point3acres
  45.                 item['content'] = ''.join(content_list)
  46.             else:
    .鐣欏璁哄潧-涓浜-涓夊垎鍦
  47.                 print 'None'. 鐣欏鐢宠璁哄潧-涓浜╀笁鍒嗗湴
  48.             if item['content'] == '':
  49.                 item['content'] = "null"
  50.             yield item
  51.             time.sleep(1)
  52. . Waral 鍗氬鏈夋洿澶氭枃绔,
  53.         except:
  54.             pass. 涓浜-涓夊垎-鍦帮紝鐙鍙戝竷
  55.      
复制代码
步骤五:设置存储文件的方式和项目设置

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


  2. SPIDER_MODULES = ['news.spiders']
  3. NEWSPIDER_MODULE = 'news.spiders'. From 1point 3acres bbs
  4. ITEM_PIPELINES = [
  5.     'news.pipelines.NewsPipeline']
  6. . 1point 3acres 璁哄潧
  7. USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; rv:38.0) Gecko/20100101 Firefox/38.0'
复制代码
其实,前面那几行都已经自动生成好了,我们所需要做的仅仅只是设置一个user_agent而已。这个东西,自己去常用的浏览器找找看能不能看到吧。. 鍥磋鎴戜滑@1point 3 acres

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

然后是对项目储存方式的设置:
打开之前生成的pipelines.py,进行编译
  1. import json
  2. import codecs
  3. from os import path
  4. from scrapy import signals
  5. . 鐗涗汉浜戦泦,涓浜╀笁鍒嗗湴
  6. class NewsPipeline(object):
  7.     def __init__(self):
  8.         self.file = codecs.open('raw_data.json', 'w',"utf-8"). more info on 1point3acres.com
  9.     def process_item(self, item, spider):
  10.         line = json.dumps(dict(item)) + "\n"
  11.         self.file.write(line)
  12.         return item
复制代码
将数据保存为json文件,方便之后转换成数据库文件。

当然,如果你想直接需要用,而不是看那些json文件里面看不懂的unicode编码的话,我下面介绍一种可以直接拿出来用的保存方式。
  1. import json. 鐣欏鐢宠璁哄潧-涓浜╀笁鍒嗗湴
  2. import codecs
  3. from os import path. 1point3acres.com/bbs
  4. from scrapy import signals

  5. class NewsPipeline(object):
  6.     def __init__(self):. from: 1point3acres.com/bbs
  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") 鏉ユ簮涓浜.涓夊垎鍦拌鍧.
  10.         self.file.write(item['link']+"\n")
  11.         self.file.write(item['date']+"\n")
  12.         self.file.write(item['content']+"\n")
  13.         return item
  14.         file.close()
复制代码

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

.鐣欏璁哄潧-涓浜-涓夊垎鍦
. 鍥磋鎴戜滑@1point 3 acres
在news文件夹下,按住shift右击,然后选择进入命令窗口,输入:
scrapy crawl hong     #hong是我们其中一个spider的name

就可以开始爬啦。
. Waral 鍗氬鏈夋洿澶氭枃绔,
提取数据的文件将保存在当前目录下。
. 1point3acres.com/bbs

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

. From 1point 3acres bbs


. From 1point 3acres bbs





. 1point 3acres 璁哄潧
. From 1point 3acres bbs

评分

12

查看全部评分

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

使用道具 举报

 楼主| victorsterling 发表于 2015-6-27 21:07:39 | 显示全部楼层
关注一亩三分地微博:
Warald
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也很好用。

最近用了一下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, 2017-3-30 15:20

Powered by Discuz! X3

© 2001-2013 Comsenz Inc. Design By HUXTeam

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