去哪儿网图片爬虫及Scrapy使用详解

本文分为两部分,去哪儿网图片爬虫和Scrapy使用详解。Scrapy使用详解基于去哪儿网图片爬虫进行解析说明。

去哪儿网图片爬虫

  • 目录结构
$ scrapy startproject TourLib

Scrapy组件说明

  1. Scrapy Engine(Scrapy引擎)
    Scrapy引擎是用来控制整个系统的数据处理流程,并进行事务处理的触发。更多的详细内容可以看下面的数据处理流程。
  2. Scheduler(调度)
    调度程序从Scrapy引擎接受请求并排序列入队列,并在Scrapy引擎发出请求后返还给他们。
  3. Downloader(下载器)
    下载器的主要职责是抓取网页并将网页内容返还给蜘蛛( Spiders)。
  4. Spiders(蜘蛛)
    蜘蛛是有Scrapy用户自己定义用来解析网页并抓取制定URL返回的内容的类,是用来定义特定网站的抓取和解析规则。
    蜘蛛的整个抓取流程(周期)是这样的:
  • 首先获取第一个URL的初始请求,当请求返回后调取一个回调函数(parse(self, response))。第一个请求是通过调用start_requests()方法。该方法默认从start_urls中的Url中生成请求,并执行解析来调用回调函数。
  • 在回调函数(parse)中,你可以解析网页响应并返回项目对象和请求对象或两者的迭代。这些请求也将包含一个回调(scrapy.Request(links, callback=self.parse_item)),然后被Scrapy下载,然后有指定的回调parse_item
    (self, response)处理。
  • 在回调函数parse_item中,你解析网站的内容,使用的是Xpath选择器(但是你也可以使用BeautifuSoup, lxml或其他任何你喜欢的程序),并生成解析的数据项。
  • 最后,从蜘蛛返回的项目通常会进驻到Item Pipeline(项目管道)。
  1. Item Pipeline(项目管道)
    项目管道的主要责任是负责处理有蜘蛛从网页中抽取的项目,他的主要任务是清洗、验证和存储数据。当页面被蜘蛛解析后,将被发送到项目管道,并经过几个特定的次序处理数据。每个项目管道的组件都是有一个简单的方法组成的Python类。他们获取了项目并执行他们的方法,同时他们还需要确定的是是否需要在项目管道中继续执行下一步或是直接丢弃掉不处理。
    项目管道通常执行的过程有:
  • 清洗HTML数据
  • 验证解析到的数据(检查项目是否包含必要的字段)
  • 检查是否是重复数据(如果重复就删除)
  • 将解析到的数据存储到数据库,将解析到的图片存储到硬盘
    piplines就干了两件事,每次spider处理好一个页面,将图片信息传给它,1.图片存到硬盘,2.信息存到数据库
  1. Downloader middlewares(下载器中间件)
    下载中间件是位于Scrapy引擎和下载器之间的钩子框架,主要是处理 Scrapy引擎与下载器之间的请求及响应。它提供了一个自定义的代码的方式来拓展Scrapy的功能。下载中间器是一个处理请求和响应的钩子框架。他是 轻量级的,对Scrapy尽享全局控制的底层的系统。
  2. Spider middlewares(蜘蛛中间件)
    蜘蛛中间件是介于Scrapy引擎和蜘蛛之间的钩子框架,主要工作是处理蜘蛛 的响应输入和请求输出。它提供一个自定义代码的方式来拓展Scrapy的功能。蛛中间件是一个挂接到Scrapy的蜘蛛处理机制的框架,你可以插入自定义 的代码来处理发送给蜘蛛的请求和返回蜘蛛获取的响应内容和项目。
  3. Scheduler middlewares(调度中间件)
    调度中间件是介于Scrapy引擎和调度之间的中间件,主要工作是处从Scrapy引擎发送到调度的请求和响应。他提供了一个自定义的代码来拓展Scrapy的功能。前阵子想爬点二手车数据赚钱,专门捣鼓了一两个星期的scrapy,虽然最后因为各种原因,赚钱并不如意,但也学到了爬虫的一些基本技术,现在记录下来,以备后续使用。

添加mysql支持

  1. settings.py中添加如下配置项
# start MySQL database configure setting
MYSQL_HOST = 'localhost'
MYSQL_DBNAME = 'cnblogsdb'
MYSQL_USER = 'root'
MYSQL_PASSWD = 'root'
# end of MySQL database configure setting
  1. 在piplines.py中添加数据库操作如下:
class ImageDownloadPipeline(object):
    def process_item(self, item, spider):
           db = MySQLdb.connect("localhost","root","mypassword","test_db" )  
           cursor = db.cursor()  
           if 'image_urls' in item:
                images = []
                dir_path = '%s/%s/%s' % (settings.IMAGES_STORE,item['place'],item['name'])
                ##item['url'] = <200 www.explame.com>
                urls = str(item['url'])[5:-1]

                if not os.path.exists(dir_path):
                    os.makedirs(dir_path)
                for image_url in item['image_urls']:
                    image_file_name = image_url[-15:]
                    file_path = '%s/%s' % (dir_path, image_file_name)
                    images.append(file_path)
                    if os.path.exists(file_path):
                         continue
                    with open(file_path, 'wb') as handle:
                         response = requests.get(image_url, stream=True)
                         for block in response.iter_content(1024):
                             if not block:
                                 break
                             handle.write(block)

                    sql = "INSERT INTO tour_tbl (tour_title,tour_icourl,local_url) VALUES ( '%s','%s','%s' )" % ( image_file_name,image_url,urls)  
                    try:  
                       # 执行sql语句  
                       cursor.execute(sql)  
                       # 提交到数据库执行  
                       db.commit()  
                    except:  
                       # 发生错误时回滚  
                       db.rollback()            

                item['images'] = images

            # 关闭数据库连接  
           db.close()  
           return item
  1. 在settins.py中添加ImageDownloadPipeline
ITEM_PIPELINES = {'qunar.pipelines.ImageDownloadPipeline': 1}

Xpath使用

示例

xpath类似beautifulsoup解析html结构,省去了正则表达式的麻烦

<html>
<head></head>
<body>
<div>
 <p><a href="http://www.iana.org"> more information </a></p>
</div>
</body>
</html>
  • xpath('//div//a')
    [<a href="http://www.iana.org"> more information </a>]
  • xpath('//div/*')
    div中所有元素
  • xpath('//div/a/@href')
    [http://www.iana.org]
  • xpath('//div/a/text()').extract()
    'more information'
xpath参考教程

这是个视频教程,是我学习xpath的最好的教程,看完真的是一下就明白了。
XPath 与多线程爬虫
Scrapy定向爬虫教程(二)——提取网页内容

多页面爬取

多页面爬取有两种形式

1)从某一个或者多个主页中获取多个子页面的url列表,parse()函数依次爬取列表中的各个子页面。

#先获取url list,然后根据list爬取各个子页面内容  
fromtutorial.items import DmozItem  
   
classDmozSpider(scrapy.Spider):  
    name = "dmoz"  
    allowed_domains = ["dmoz.org"]  
    start_urls =["http://www.dmoz.org/Computers/Programming/Languages/Python/",]  
   
    def parse(self, response):  
        for href inresponse.css("ul.directory.dir-col > li > a::attr('href')"):  
#获取当前页面的url:respone.url  
#通过拼接response.url和href.extract(),将相对网址转换为绝对网址  
            url =response.urljoin(response.url, href.extract())  
            yield scrapy.Request(url, callback=self.parse_dir_contents)  
   
         #负责子页面内容的爬取  
    def parse_dir_contents(self, response):  
        for sel in response.xpath('//ul/li'):  
            item = DmozItem()  
            item['title'] =sel.xpath('a/text()').extract()  
            item['link'] = sel.xpath('a/@href').extract()  
            item['desc'] =sel.xpath('text()').extract()  
            yield item  

2)从递归爬取,这个相对简单。在scrapy中只要定义好初始页面以及爬虫规则rules,就能够实现自动化的递归爬取。

yield和return的区别
  • yield
    yield是用于生成器。什么是生成器,你可以通俗的认为,在一个函数中,使用了yield来代替return的位置的函数,就是生成器。它不同于函数的使用方法是:函数使用return来进行返回值,每调用一次,返回一个新加工好的数据返回给你;yield不同,它会在调用生成器的时候,把数据生成object,然后当你需要用的时候,要用next()方法来取,同时不可逆。你可以通俗的叫它"轮转容器",可用现实的一种实物来理解:水车,先yield来装入数据、产出generator object、使用next()来释放;好比水车转动后,车轮上的水槽装入水,随着轮子转动,被转到下面的水槽就能将水送入水道中流入田里。
def func3():
    for i in range(1,5):
        yield i#装入
 
gob = func3()#generator 类型
print next(gob)#1    释放的第一个装入的数据,(先入先出)
print next(gob)#2
print next(gob)#3
print next(gob)#4
 
print next(gob)#报错

个人理解,yield在python内部是当作list处理的:

def func3():
    for i in range(1,5):
        yield i
        
yi = []
yi = func3()
for y in yi:
    print y

输出:    
1
2
3
4
  • return
    这个大家都知道,return既可以终止函数的执行,也可以返回函数加工处理好的数据。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容