Scrapy复习


python爬虫之Scrapy 使用代理配置
在爬取网站内容的时候,最常遇到的问题是:网站对IP有限制,会有防抓取功能,最好的办法就是IP轮换抓取(加代理)

下面来说一下Scrapy如何配置代理,进行抓取

1.在Scrapy工程下新建“middlewares.py”
# Importing base64 library because we'll need it ONLY in case if the proxy we are going to use requires authentication
import base64
# Start your middleware class
class ProxyMiddleware(object):
    # overwrite process request
    def process_request(self, request, spider):
        # Set the location of the proxy
        request.meta['proxy'] = "http://YOUR_PROXY_IP:PORT"
 
        # Use the following lines if your proxy requires authentication
        proxy_user_pass = "USERNAME:PASSWORD"
        # setup basic authentication for the proxy
        encoded_user_pass = base64.encodestring(proxy_user_pass)
        request.headers['Proxy-Authorization'] = 'Basic ' + encoded_user_pass

2.在项目配置文件里(./pythontab/settings.py)添加
DOWNLOADER_MIDDLEWARES = {
    'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware': 110,
    'pythontab.middlewares.ProxyMiddleware': 100,
}

Scrapy框架中Item Pipeline组件(项目管道组件)的使用教程
http://blog.csdn.net/php_fly/article/details/19571121
Item Pipeline简介
Item管道的主要责任是负责处理有蜘蛛从网页中抽取的Item,他的主要任务是清晰、验证和存储数据。
当页面被蜘蛛解析后,将被发送到Item管道,并经过几个特定的次序处理数据。
每个Item管道的组件都是有一个简单的方法组成的Python类。
他们获取了Item并执行他们的方法,同时他们还需要确定的是是否需要在Item管道中继续执行下一步或是直接丢弃掉不处理。
Item管道通常执行的过程有
    清理HTML数据
    验证解析到的数据(检查Item是否包含必要的字段)
    检查是否是重复数据(如果重复就删除)

    将解析到的数据存储到数据库中


编写自己的Item Pipeline
编写item管道其实是很容易的。
每个Item管道的组件都是由一个简单的方法组成的Python类:

    process_item(item, spider)
每一个item管道组件都会调用该方法,并且必须返回一个item对象实例或raise DropItem异常。被丢掉的item将不会在管道组件进行执行, 此外,我们也可以在类中实现以下方法open_spider(spider),当spider执行的时候将调用该方法close_spider(spider),当spider关闭的时候将调用该方法

Item Pipeline例子
代码如下:
[python] view plaincopy在CODE上查看代码片派生到我的代码片
    from scrapy.exceptions import DropItem        
    class PricePipeline(object):        
        vat_factor = 1.15        
        def process_item(self, item, spider):  
            if item['price']:  
                if item['price_excludes_vat']:  
                    item['price'] = item['price'] * self.vat_factor  
                return item  
            else:  
                raise DropItem("Missing price in %s" % item)  

注:VAT:Value Added Tax(增值税)
以上代码可以过滤那些没有价格的产品,并且对那些不包括增值税产品的价格进行调整

将抓取的items以json格式保存到文件中
从spider抓取到的items将被序列化为json格式,并且以每行一个item的形式被写入到items.jl文件中
代码:[python] view plaincopy在CODE上查看代码片派生到我的代码片
    import json  
      
    class JsonWriterPipeline(object):  
      
        def __init__(self):  
            self.file = open('items.jl', 'wb')  
      
        def process_item(self, item, spider):  
            line = json.dumps(dict(item)) + "\n"  
            self.file.write(line)  
            return item  

注:JsonWriterPipeline的目的是介绍如何编写项目管道。如果想要保存抓取的items到json文件中,推荐使用Feed exports
删除重复项
假设在spider中提取到的item有重复的id,那么我们就可以在process_item函数中进行过滤
如:
[python] view plaincopy在CODE上查看代码片派生到我的代码片
    from scrapy.exceptions import DropItem  
      
    class DuplicatesPipeline(object):  
      
        def __init__(self):  
            self.ids_seen = set()  
      
        def process_item(self, item, spider):  
            if item['id'] in self.ids_seen:  
                raise DropItem("Duplicate item found: %s" % item)  
            else:  
                self.ids_seen.add(item['id'])  
                return item  

激活Item Pipeline组件
在settings.py文件中,往ITEM_PIPELINES中添加项目管道的类名,就可以激活项目管道组件
如:[python] view plaincopy在CODE上查看代码片派生到我的代码片
    ITEM_PIPELINES = {  
        'myproject.pipeline.PricePipeline': 300,  
        'myproject.pipeline.JsonWriterPipeline': 800,  
    }  
The integer values you assign to classes in this setting determine the order they run in- items go through pipelines from order number low to high

整数值通常设置在0-1000之间
作者:曾是土木人(http://blog.csdn.net/php_fly)

原文地址:http://blog.csdn.net/php_fly/article/details/19571121


一次性运行多个Spiders
http://blog.csdn.net/iefreer/article/details/20677943
如果创建了多个Spider,希望通过cronjob一次性运行所有的Spiders,可以通过自定义Scrapy命令来实现。

1. 在你的Scrapy工程下面新建一个目录:
cd path/to/your_project
mkdir commands
注意这个commands和spiders目录是同级的


2. 在commands下面添加一个文件crawlall.py,代码如下:
[python] view plaincopy在CODE上查看代码片派生到我的代码片   

from scrapy.command import ScrapyCommand  
    from scrapy.utils.project import get_project_settings  
    from scrapy.crawler import Crawler       
    class Command(ScrapyCommand):       
        requires_project = True       
        def syntax(self):  
            return '[options]'  
      
        def short_desc(self):  
            return 'Runs all of the spiders'  
      
        def run(self, args, opts):  
            settings = get_project_settings()  
      
            for spider_name in self.crawler.spiders.list():  
                crawler = Crawler(settings)  
                crawler.configure()  
                spider = crawler.spiders.create(spider_name)  
                crawler.crawl(spider)  
                crawler.start()       
            self.crawler.start()  

3. 在settings.py中添加配置:
COMMANDS_MODULE = 'yourprojectname.commands'

4. 在cronjob中添加:scrapy crawlall命令即可

Here is an example that does not run inside a custom command, but runs the Reactor manually and creates a new Crawler for each spider:

from twisted.internet import reactor
from scrapy.crawler import Crawler
# scrapy.conf.settings singlton was deprecated last year
from scrapy.utils.project import get_project_settings
from scrapy import log

def setup_crawler(spider_name):
    crawler = Crawler(settings)
    crawler.configure()
    spider = crawler.spiders.create(spider_name)
    crawler.crawl(spider)
    crawler.start()

log.start()
settings = get_project_settings()
crawler = Crawler(settings)
crawler.configure()

for spider_name in crawler.spiders.list():
    setup_crawler(spider_name)

reactor.run()


You will have to design some signal system to stop the reactor when all spiders are finished.
EDIT: And here is how you can run multiple spiders in a custom command:
from scrapy.command import ScrapyCommand
from scrapy.utils.project import get_project_settings
from scrapy.crawler import Crawler

class Command(ScrapyCommand):

    requires_project = True

    def syntax(self):
        return '[options]'

    def short_desc(self):
        return 'Runs all of the spiders'

    def run(self, args, opts):
        settings = get_project_settings()

        for spider_name in self.crawler.spiders.list():
            crawler = Crawler(settings)
            crawler.configure()
            spider = crawler.spiders.create(spider_name)
            crawler.crawl(spider)
            crawler.start()

        self.crawler.start()

定制请求头

如果你想为请求添加HTTP头部,只要简单地传递一个 dict 给 headers 参数就可以了。

例如,在前一个示例中我们没有指定content-type:

>>> import json
>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}
>>> headers = {'content-type': 'application/json'}

>>> r = requests.post(url, data=json.dumps(payload), headers=headers)

更加复杂的POST请求

通常,你想要发送一些编码为表单形式的数据—非常像一个HTML表单。 要实现这个,只需简单地传递一个字典给 data 参数。你的数据字典 在发出请求时会自动编码为表单形式:

>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.post("http://httpbin.org/post", data=payload)
>>> print r.text
{
  ...
  "form": {
    "key2": "value2",
    "key1": "value1"
  },
  ...
}

很多时候你想要发送的数据并非编码为表单形式的。如果你传递一个 string 而不是一个dict ,那么数据会被直接发布出去。

例如,Github API v3接受编码为JSON的POST/PATCH数据:

>>> import json
>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}

>>> r = requests.post(url, data=json.dumps(payload))

POST一个多部分编码(Multipart-Encoded)的文件

Requests使得上传多部分编码文件变得很简单:

>>> url = 'http://httpbin.org/post'
>>> files = {'file': open('report.xls', 'rb')}

>>> r = requests.post(url, files=files)
>>> r.text
{
  ...
  "files": {
    "file": "<censored...binary...data>"
  },
  ...
}

你可以显式地设置文件名:

>>> url = 'http://httpbin.org/post'
>>> files = {'file': ('report.xls', open('report.xls', 'rb'))}

>>> r = requests.post(url, files=files)
>>> r.text
{
  ...
  "files": {
    "file": "<censored...binary...data>"
  },
  ...
}

如果你想,你也可以发送作为文件来接收的字符串:

>>> url = 'http://httpbin.org/post'
>>> files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')}

>>> r = requests.post(url, files=files)
>>> r.text
{
  ...
  "files": {
    "file": "some,data,to,send\\nanother,row,to,send\\n"
  },
  ...
}

响应头

我们可以查看以一个Python字典形式展示的服务器响应头:

>>> r.headers
{
    'status': '200 OK',
    'content-encoding': 'gzip',
    'transfer-encoding': 'chunked',
    'connection': 'close',
    'server': 'nginx/1.0.4',
    'x-runtime': '148ms',
    'etag': '"e1ca502697e5c9317743dc078f67693f"',
    'content-type': 'application/json; charset=utf-8'
}

但是这个字典比较特殊:它是仅为HTTP头部而生的。根据 RFC 2616 , HTTP头部是大小写不敏感的。

因此,我们可以使用任意大写形式来访问这些响应头字段:

>>> r.headers['Content-Type']
'application/json; charset=utf-8'

>>> r.headers.get('content-type')
'application/json; charset=utf-8'

如果某个响应头字段不存在,那么它的默认值为 None

>>> r.headers['X-Random']
None

Cookies

如果某个响应中包含一些Cookie,你可以快速访问它们:

>>> url = 'http://example.com/some/cookie/setting/url'
>>> r = requests.get(url)

>>> r.cookies['example_cookie_name']
'example_cookie_value'

要想发送你的cookies到服务器,可以使用 cookies 参数:

>>> url = 'http://httpbin.org/cookies'
>>> cookies = dict(cookies_are='working')

>>> r = requests.get(url, cookies=cookies)
>>> r.text
'{"cookies": {"cookies_are": "working"}}'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值