《数据科学面试40+真题讲解》,K神本年度最后一次开课


一亩三分地论坛

 找回密码
 Sign Up 注册获取更多干货
码农求职神器Triplebyte:
不用海投,内推你去多家公司面试
Airbnb 数据科学职位
in analytics and inference
天天打游戏、照样领工资,
你要不要来?
把贵司招聘信息放这里
查看: 11325|回复: 9
收起左侧

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

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

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

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

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去做网络爬虫。. visit 1point3acres.com for more.


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


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

对python有了一定了解后,请安装好pyhton,设置好环境参量,并安装scrapy模块,教程如下:
installation guide
.鐣欏璁哄潧-涓浜-涓夊垎鍦
. 1point3acres.com/bbs
其它需要的module在实际应用中,就见到需要什么就装什么,反正大多都可以在shell(cmd)中用pip install XX 就可以了。

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

首先,打开cmd,输入scrapy startproject news
就可以创建一个名字为news的项目。一般默认在我的文档目录下生成文件。文件目录如下:
news:.│  scrapy.cfg
│└─news   
   │  items.py   
   │  pipelines.py    鏉ユ簮涓浜.涓夊垎鍦拌鍧.
   │  settings.py   
   │  __init__.py    . Waral 鍗氬鏈夋洿澶氭枃绔,
   │ └─spiders           
             __init__.py
  • scrapy.cfg: 项目配置文件
  • news/: 项目python模块, 呆会代码将从这里导入
  • news/items.py: 项目items文件
  • news/pipelines.py: 项目管道文件
  • news/settings.py: 项目配置文件
  • news/spiders: 放置spider的目录
-google 1point3acres
步骤三:定义我们要提取的数据(item)
. from: 1point3acres.com/bbs
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(). more info on 1point3acres.com
  6.     content = Field()
  7.     date = Field()
复制代码
步骤四:写爬虫(spider). 鐣欏鐢宠璁哄潧-涓浜╀笁鍒嗗湴


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


其中最简单的是BaseSpider,最常用的是CrawlSpider,在这里我对这俩种进行介绍:
. visit 1point3acres.com for more.

进入spider目录,在这个目录下新建一个py文件,名字就是spider的name,然后进行编辑。
. 鐗涗汉浜戦泦,涓浜╀笁鍒嗗湴

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

  7. .1point3acres缃
  8. class SohuSpider(scrapy.Spider):
  9.     name = "sohu"
  10.     allowed_domains = ["gongyi.sohu.com"]
  11.     start_urls = (. from: 1point3acres.com/bbs
  12.                 'http://gongyi.sohu.com/hbdt/',
  13.                 #'http://gongyi.sohu.com/gongyiyw/'. from: 1point3acres.com/bbs
  14.                 #'http://gongyi.sohu.com/salon/index.shtml'
  15.                 #'http://gongyi.sohu.com/focus/index.shtml'
  16.                 #'http://gongyi.sohu.com/gongyicehua/'
  17.         ). 1point3acres.com/bbs
  18.     def __init__(self):-google 1point3acres
  19.         
  20.         self.count = 33

  21.     def parse(self, response):. more info on 1point3acres.com
  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].1point3acres缃
  27.                 if not li.xpath('a/text()'):
  28.                         continue
  29.                 item['title'] = li.xpath('a/text()').extract()[0]. 1point3acres.com/bbs
  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.鏈枃鍘熷垱鑷1point3acres璁哄潧
  37.                 link_list = re.findall('<p>(.*?)</p>' ,data)
  38.                 item["content"] = ''
  39.                 if  link_list:. 鐗涗汉浜戦泦,涓浜╀笁鍒嗗湴
  40.                     item["content"] = ''.join(link_list). 鍥磋鎴戜滑@1point 3 acres
  41.                 else :. visit 1point3acres.com for more.
  42.                     print 'NONE'. more info on 1point3acres.com
  43.                 yield item
  44. . 鐗涗汉浜戦泦,涓浜╀笁鍒嗗湴
  45.         except:
  46.             pass


  47.         if self.count>0:
  48.             url = "http://gongyi.sohu.com/hbdt/index_" + str(self.count) + ".shtml"
  49.             print url
  50.             self.count -= 1. from: 1point3acres.com/bbs
  51.             yield Request(url, callback = self.parse)
复制代码
其次是CrawlSpider:
这个就更加粗暴一些,通rule规则去爬此网站域名下所有的网页,再根规则从中选择想要提取数据的网页进行数据提取,(简单粗暴,不过感觉大数据分析抓数据就该这么粗暴地大规模抓数据吧
. 鐗涗汉浜戦泦,涓浜╀笁鍒嗗湴
.鏈枃鍘熷垱鑷1point3acres璁哄潧
下面是一个爬地方性新闻网站的例子。
  1. #-*-coding:utf-8-*-
  2. #Author: Victor
  3. #Date: 2015-6-18
  4. import re
  5. import scrapy.鏈枃鍘熷垱鑷1point3acres璁哄潧
  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. from news.items import NewsItem

  13. class HongSpider(CrawlSpider):-google 1point3acres
  14.     name = 'hong'
    . 涓浜-涓夊垎-鍦帮紝鐙鍙戝竷

  15.     allowed_domains = ['rednet.cn']
    . Waral 鍗氬鏈夋洿澶氭枃绔,
  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)),
  20.         
  21.         )
  22. 鏉ユ簮涓浜.涓夊垎鍦拌鍧.

  23.     def parse_item(self, response):. 1point3acres.com/bbs
  24.         try:. 1point 3acres 璁哄潧
  25.             hxs = HtmlXPathSelector(response).鐣欏璁哄潧-涓浜-涓夊垎鍦
  26.             item = NewsItem(). 鐗涗汉浜戦泦,涓浜╀笁鍒嗗湴
  27.             item['link'] = response.url
    . 1point3acres.com/bbs
  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().1point3acres缃
  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().1point3acres缃
  42.             if content_list ==[]:
  43.                 content_list = hxs.select("//div[@id='zoom']/text()").extract()
  44.             if content_list:
  45.                 item['content'] = ''.join(content_list)
  46.             else:. From 1point 3acres bbs
  47.                 print 'None'
  48.             if item['content'] == '':.1point3acres缃
  49.                 item['content'] = "null"
    -google 1point3acres
  50.             yield item
  51.             time.sleep(1)
  52. .1point3acres缃
  53.         except:
  54.             pass
  55.      
复制代码
步骤五:设置存储文件的方式和项目设置


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


  2. SPIDER_MODULES = ['news.spiders']
  3. NEWSPIDER_MODULE = 'news.spiders'
  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而已。这个东西,自己去常用的浏览器找找看能不能看到吧。
. 鐗涗汉浜戦泦,涓浜╀笁鍒嗗湴
虽然我觉得这东西并没有什么卵用······我之前忘记设置了也照样能爬。不过还是严谨一点比较好。
. 鍥磋鎴戜滑@1point 3 acres
然后是对项目储存方式的设置:
打开之前生成的pipelines.py,进行编译
  1. import json. 1point3acres.com/bbs
  2. import codecs. 1point 3acres 璁哄潧
  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.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):        
    . more info on 1point3acres.com
  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()
复制代码

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


鏉ユ簮涓浜.涓夊垎鍦拌鍧.
在news文件夹下,按住shift右击,然后选择进入命令窗口,输入:
scrapy crawl hong     #hong是我们其中一个spider的name

就可以开始爬啦。.1point3acres缃
. 鍥磋鎴戜滑@1point 3 acres
提取数据的文件将保存在当前目录下。


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












评分

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. more info on 1point3acres.com
谢谢LZ分享。还有一个BeautifulSoup也很好用。

最近用了一下beautifulsoup,感觉这个跟scrapy相比还是差很多啊,很难实现一些html节点的精准抓取,只是一些常用的,笼统的数据提取,感觉不是很有效力。还是说我自己的用的不地道??
回复 支持 反对

使用道具 举报

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

使用道具 举报

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

使用道具 举报

本版积分规则

关闭

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

手机版|小黑屋|一亩三分地论坛声明

custom counter

GMT+8, 2017-11-24 13:43

Powered by Discuz! X3

© 2001-2013 Comsenz Inc. Design By HUXTeam

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