Scrapy复习

来源:互联网 发布:淘宝收藏代码在线生成 编辑:程序博客网 时间:2024/06/11 00:13

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 authenticationimport base64# Start your middleware classclass 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 reactorfrom scrapy.crawler import Crawler# scrapy.conf.settings singlton was deprecated last yearfrom scrapy.utils.project import get_project_settingsfrom scrapy import logdef 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 ScrapyCommandfrom scrapy.utils.project import get_project_settingsfrom scrapy.crawler import Crawlerclass 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"}}'
0 0
原创粉丝点击