Merge branch 'master' into enhancement/alternate-feedexport-constructors

This commit is contained in:
Eugenio Lacuesta 2018-07-20 12:09:50 -03:00
commit 917c1fde68
236 changed files with 1795 additions and 1260 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 1.4.0
current_version = 1.5.0
commit = True
tag = True
tag_name = {new_version}

View File

@ -5,15 +5,4 @@ omit =
tests/*
scrapy/xlib/*
scrapy/conf.py
scrapy/stats.py
scrapy/project.py
scrapy/utils/decorator.py
scrapy/statscol.py
scrapy/squeue.py
scrapy/log.py
scrapy/dupefilter.py
scrapy/command.py
scrapy/linkextractor.py
scrapy/spider.py
scrapy/contrib/*
scrapy/contrib_exp/*

View File

@ -13,27 +13,34 @@ matrix:
env: TOXENV=jessie
- python: 2.7
env: TOXENV=pypy
- python: 3.3
env: TOXENV=py33
- python: 2.7
env: TOXENV=pypy3
- python: 3.4
env: TOXENV=py34
- python: 3.5
env: TOXENV=py35
- python: 3.6
env: TOXENV=py36
- python: 3.7
env: TOXENV=py37
dist: xenial
sudo: true
- python: 3.6
env: TOXENV=docs
install:
- |
if [ "$TOXENV" = "pypy" ]; then
export PYENV_ROOT="$HOME/.pyenv"
if [ -f "$PYENV_ROOT/bin/pyenv" ]; then
pushd "$PYENV_ROOT" && git pull && popd
else
rm -rf "$PYENV_ROOT" && git clone --depth 1 https://github.com/yyuu/pyenv.git "$PYENV_ROOT"
fi
# get latest portable PyPy from pyenv directly (thanks to natural version sort option -V)
export PYPY_VERSION=`"$PYENV_ROOT/bin/pyenv" install --list |grep -o -E 'pypy-portable-[0-9][\.0-9]*$' |sort -V |tail -1`
"$PYENV_ROOT/bin/pyenv" install --skip-existing "$PYPY_VERSION"
virtualenv --python="$PYENV_ROOT/versions/$PYPY_VERSION/bin/python" "$HOME/virtualenvs/$PYPY_VERSION"
export PYPY_VERSION="pypy-6.0.0-linux_x86_64-portable"
wget "https://bitbucket.org/squeaky/portable-pypy/downloads/${PYPY_VERSION}.tar.bz2"
tar -jxf ${PYPY_VERSION}.tar.bz2
virtualenv --python="$PYPY_VERSION/bin/pypy" "$HOME/virtualenvs/$PYPY_VERSION"
source "$HOME/virtualenvs/$PYPY_VERSION/bin/activate"
fi
if [ "$TOXENV" = "pypy3" ]; then
export PYPY_VERSION="pypy3.5-5.9-beta-linux_x86_64-portable"
wget "https://bitbucket.org/squeaky/portable-pypy/downloads/${PYPY_VERSION}.tar.bz2"
tar -jxf ${PYPY_VERSION}.tar.bz2
virtualenv --python="$PYPY_VERSION/bin/pypy3" "$HOME/virtualenvs/$PYPY_VERSION"
source "$HOME/virtualenvs/$PYPY_VERSION/bin/activate"
fi
- pip install -U tox twine wheel codecov

View File

@ -3,7 +3,7 @@
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and

View File

@ -1,6 +1,6 @@
The guidelines for contributing are available here:
http://doc.scrapy.org/en/master/contributing.html
https://doc.scrapy.org/en/master/contributing.html
Please do not abuse the issue tracker for support questions.
If your issue topic can be rephrased to "How to ...?", please use the
support channels to get it answered: http://scrapy.org/community/
support channels to get it answered: https://scrapy.org/community/

View File

@ -1,4 +1,4 @@
For information about installing Scrapy see:
* docs/intro/install.rst (local file)
* http://doc.scrapy.org/en/latest/intro/install.html (online version)
* https://doc.scrapy.org/en/latest/intro/install.html (online version)

View File

@ -5,10 +5,10 @@ Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of Scrapy nor the names of its contributors may be used

View File

@ -6,8 +6,12 @@ Scrapy
:target: https://pypi.python.org/pypi/Scrapy
:alt: PyPI Version
.. image:: https://img.shields.io/pypi/pyversions/Scrapy.svg
:target: https://pypi.python.org/pypi/Scrapy
:alt: Supported Python Versions
.. image:: https://img.shields.io/travis/scrapy/scrapy/master.svg
:target: http://travis-ci.org/scrapy/scrapy
:target: https://travis-ci.org/scrapy/scrapy
:alt: Build Status
.. image:: https://img.shields.io/badge/wheel-yes-brightgreen.svg
@ -15,7 +19,7 @@ Scrapy
:alt: Wheel Status
.. image:: https://img.shields.io/codecov/c/github/scrapy/scrapy/master.svg
:target: http://codecov.io/github/scrapy/scrapy?branch=master
:target: https://codecov.io/github/scrapy/scrapy?branch=master
:alt: Coverage report
.. image:: https://anaconda.org/conda-forge/scrapy/badges/version.svg
@ -31,12 +35,12 @@ crawl websites and extract structured data from their pages. It can be used for
a wide range of purposes, from data mining to monitoring and automated testing.
For more information including a list of features check the Scrapy homepage at:
http://scrapy.org
https://scrapy.org
Requirements
============
* Python 2.7 or Python 3.3+
* Python 2.7 or Python 3.4+
* Works on Linux, Windows, Mac OSX, BSD
Install
@ -47,12 +51,12 @@ The quick way::
pip install scrapy
For more details see the install section in the documentation:
http://doc.scrapy.org/en/latest/intro/install.html
https://doc.scrapy.org/en/latest/intro/install.html
Documentation
=============
Documentation is available online at http://doc.scrapy.org/ and in the ``docs``
Documentation is available online at https://doc.scrapy.org/ and in the ``docs``
directory.
Releases
@ -63,12 +67,12 @@ You can find release notes at https://doc.scrapy.org/en/latest/news.html
Community (blog, twitter, mail list, IRC)
=========================================
See http://scrapy.org/community/
See https://scrapy.org/community/
Contributing
============
See http://doc.scrapy.org/en/master/contributing.html
See https://doc.scrapy.org/en/master/contributing.html
Code of Conduct
---------------
@ -82,9 +86,9 @@ Please report unacceptable behavior to opensource@scrapinghub.com.
Companies using Scrapy
======================
See http://scrapy.org/companies/
See https://scrapy.org/companies/
Commercial Support
==================
See http://scrapy.org/support/
See https://scrapy.org/support/

View File

@ -10,10 +10,10 @@ scrapy-logo.jpg
Main Scrapy logo, in JPEG format.
qlassik.zip
qlassik.zip
-----------
Font used for Scrapy logo. Homepage: http://www.dafont.com/qlassik.font
Font used for Scrapy logo. Homepage: https://www.dafont.com/qlassik.font
scrapy-blog.logo.xcf
--------------------

View File

@ -11,21 +11,12 @@ def _py_files(folder):
collect_ignore = [
# deprecated or moved modules
"scrapy/conf.py",
"scrapy/stats.py",
"scrapy/project.py",
"scrapy/utils/decorator.py",
"scrapy/statscol.py",
"scrapy/squeue.py",
"scrapy/log.py",
"scrapy/dupefilter.py",
"scrapy/command.py",
"scrapy/linkextractor.py",
"scrapy/spider.py",
# not a test, but looks like a test
"scrapy/utils/testsite.py",
] + _py_files("scrapy/contrib") + _py_files("scrapy/contrib_exp")
]
if (twisted_version.major, twisted_version.minor, twisted_version.micro) >= (15, 5, 0):
collect_ignore += _py_files("scrapy/xlib/tx")

6
debian/control vendored
View File

@ -4,7 +4,7 @@ Priority: optional
Maintainer: Scrapinghub Team <info@scrapinghub.com>
Build-Depends: debhelper (>= 7.0.50), python (>=2.7), python-twisted, python-w3lib, python-lxml, python-six (>=1.5.2)
Standards-Version: 3.8.4
Homepage: http://scrapy.org/
Homepage: https://scrapy.org/
Package: scrapy
Architecture: all
@ -15,6 +15,6 @@ Conflicts: python-scrapy, scrapy-0.25
Provides: python-scrapy, scrapy-0.25
Description: Python web crawling and web scraping framework
Scrapy is a fast high-level web crawling and web scraping framework,
used to crawl websites and extract structured data from their pages.
It can be used for a wide range of purposes, from data mining to
used to crawl websites and extract structured data from their pages.
It can be used for a wide range of purposes, from data mining to
monitoring and automated testing.

8
debian/copyright vendored
View File

@ -1,6 +1,6 @@
This package was debianized by the Scrapinghub team <info@scrapinghub.com>.
It was downloaded from http://scrapy.org
It was downloaded from https://scrapy.org
Upstream Author: Scrapy Developers
@ -14,10 +14,10 @@ All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

View File

@ -1,6 +1,6 @@
from docutils.parsers.rst.roles import set_classes
from docutils import nodes
from sphinx.util.compat import Directive
from docutils.parsers.rst import Directive
from sphinx.util.nodes import make_refnode
from operator import itemgetter
@ -110,24 +110,28 @@ def setup(app):
app.connect('doctree-read', collect_scrapy_settings_refs)
app.connect('doctree-resolved', replace_settingslist_nodes)
def source_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
ref = 'https://github.com/scrapy/scrapy/blob/master/' + text
set_classes(options)
node = nodes.reference(rawtext, text, refuri=ref, **options)
return [node], []
def issue_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
ref = 'https://github.com/scrapy/scrapy/issues/' + text
set_classes(options)
node = nodes.reference(rawtext, 'issue ' + text, refuri=ref, **options)
return [node], []
def commit_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
ref = 'https://github.com/scrapy/scrapy/commit/' + text
set_classes(options)
node = nodes.reference(rawtext, 'commit ' + text, refuri=ref, **options)
return [node], []
def rev_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
ref = 'http://hg.scrapy.org/scrapy/changeset/' + text
set_classes(options)

View File

@ -144,10 +144,6 @@ html_static_path = ['_static']
# using the given strftime format.
html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
@ -191,8 +187,8 @@ htmlhelp_basename = 'Scrapydoc'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, document class [howto/manual]).
latex_documents = [
('index', 'Scrapy.tex', ur'Scrapy Documentation',
ur'Scrapy developers', 'manual'),
('index', 'Scrapy.tex', u'Scrapy Documentation',
u'Scrapy developers', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of

View File

@ -6,8 +6,8 @@ Contributing to Scrapy
.. important::
Double check you are reading the most recent version of this document at
http://doc.scrapy.org/en/master/contributing.html
Double check that you are reading the most recent version of this document at
https://doc.scrapy.org/en/master/contributing.html
There are many ways to contribute to Scrapy. Here are some of them:
@ -18,13 +18,17 @@ There are many ways to contribute to Scrapy. Here are some of them:
* Report bugs and request features in the `issue tracker`_, trying to follow
the guidelines detailed in `Reporting bugs`_ below.
* Submit patches for new functionality and/or bug fixes. Please read
`Writing patches`_ and `Submitting patches`_ below for details on how to
* Submit patches for new functionalities and/or bug fixes. Please read
:ref:`writing-patches` and `Submitting patches`_ below for details on how to
write and submit a patch.
* Join the `Scrapy subreddit`_ and share your ideas on how to
improve Scrapy. We're always open to suggestions.
* Answer Scrapy questions at
`Stack Overflow <https://stackoverflow.com/questions/tagged/scrapy>`__.
Reporting bugs
==============
@ -40,9 +44,14 @@ guidelines when reporting a new bug.
* check the :ref:`FAQ <faq>` first to see if your issue is addressed in a
well-known question
* check the `open issues`_ to see if it has already been reported. If it has,
don't dismiss the report but check the ticket history and comments, you may
find additional useful information to contribute.
* if you have a general question about scrapy usage, please ask it at
`Stack Overflow <https://stackoverflow.com/questions/tagged/scrapy>`__
(use "scrapy" tag).
* check the `open issues`_ to see if the issue has already been reported. If it
has, don't dismiss the report, but check the ticket history and comments. If
you have additional useful information, please leave a comment, or consider
:ref:`sending a pull request <writing-patches>` with a fix.
* search the `scrapy-users`_ list and `Scrapy subreddit`_ to see if it has
been discussed there, or if you're not sure if what you're seeing is a bug.
@ -54,17 +63,24 @@ guidelines when reporting a new bug.
it. See for example StackOverflow's guide on creating a
`Minimal, Complete, and Verifiable example`_ exhibiting the issue.
* the most awesome way to provide a complete reproducible example is to
send a pull request which adds a failing test case to the
Scrapy testing suite (see :ref:`submitting-patches`).
This is helpful even if you don't have an intention to
fix the issue yourselves.
* include the output of ``scrapy version -v`` so developers working on your bug
know exactly which version and platform it occurred on, which is often very
helpful for reproducing it, or knowing if it was already fixed.
.. _Minimal, Complete, and Verifiable example: https://stackoverflow.com/help/mcve
.. _writing-patches:
Writing patches
===============
The better written a patch is, the higher chance that it'll get accepted and
the sooner that will be merged.
The better a patch is written, the higher the chances that it'll get accepted and the sooner it will be merged.
Well-written patches should:
@ -83,6 +99,8 @@ Well-written patches should:
the documentation changes in the same patch. See `Documentation policies`_
below.
.. _submitting-patches:
Submitting patches
==================
@ -100,14 +118,32 @@ starting point is to send a pull request on GitHub. It can be simple enough to
illustrate your idea, and leave documentation/tests for later, after the idea
has been validated and proven useful. Alternatively, you can start a
conversation in the `Scrapy subreddit`_ to discuss your idea first.
Sometimes there is an existing pull request for the problem you'd like to
solve, which is stalled for some reason. Often the pull request is in a
right direction, but changes are requested by Scrapy maintainers, and the
original pull request author hasn't had time to address them.
In this case consider picking up this pull request: open
a new pull request with all commits from the original pull request, as well as
additional changes to address the raised issues. Doing so helps a lot; it is
not considered rude as soon as the original author is acknowledged by keeping
his/her commits.
You can pull an existing pull request to a local branch
by running ``git fetch upstream pull/$PR_NUMBER/head:$BRANCH_NAME_TO_CREATE``
(replace 'upstream' with a remote name for scrapy repository,
``$PR_NUMBER`` with an ID of the pull request, and ``$BRANCH_NAME_TO_CREATE``
with a name of the branch you want to create locally).
See also: https://help.github.com/articles/checking-out-pull-requests-locally/#modifying-an-inactive-pull-request-locally.
When writing GitHub pull requests, try to keep titles short but descriptive.
E.g. For bug #411: "Scrapy hangs if an exception raises in start_requests"
prefer "Fix hanging when exception occurs in start_requests (#411)"
instead of "Fix for #411".
Complete titles make it easy to skim through the issue tracker.
instead of "Fix for #411". Complete titles make it easy to skim through
the issue tracker.
Finally, try to keep aesthetic changes (:pep:`8` compliance, unused imports
removal, etc) in separate commits than functional changes. This will make pull
removal, etc) in separate commits from functional changes. This will make pull
requests easier to review and more likely to get merged.
Coding style
@ -121,21 +157,29 @@ Scrapy:
* It's OK to use lines longer than 80 chars if it improves the code
readability.
* Don't put your name in the code you contribute. Our policy is to keep
the contributor's name in the `AUTHORS`_ file distributed with Scrapy.
* Don't put your name in the code you contribute; git provides enough
metadata to identify author of the code.
See https://help.github.com/articles/setting-your-username-in-git/ for
setup instructions.
Documentation policies
======================
* **Don't** use docstrings for documenting classes, or methods which are
already documented in the official (sphinx) documentation. For example, the
:meth:`ItemLoader.add_value` method should be documented in the sphinx
documentation, not its docstring.
already documented in the official (sphinx) documentation. Alternatively,
**do** provide a docstring, but make sure sphinx documentation uses
autodoc_ extension to pull the docstring. For example, the
:meth:`ItemLoader.add_value` method should be either
documented only in the sphinx documentation (not as a docstring), or
it should have a docstring which is pulled to sphinx documentation using
autodoc_ extension.
* **Do** use docstrings for documenting functions not present in the official
(sphinx) documentation, such as functions from ``scrapy.utils`` package and
its sub-modules.
.. _autodoc: http://www.sphinx-doc.org/en/stable/ext/autodoc.html
Tests
=====
@ -188,7 +232,7 @@ And their unit-tests are in::
.. _issue tracker: https://github.com/scrapy/scrapy/issues
.. _scrapy-users: https://groups.google.com/forum/#!forum/scrapy-users
.. _Scrapy subreddit: http://reddit.com/r/scrapy
.. _Scrapy subreddit: https://reddit.com/r/scrapy
.. _Twisted unit-testing framework: https://twistedmatrix.com/documents/current/core/development/policy/test-standard.html
.. _AUTHORS: https://github.com/scrapy/scrapy/blob/master/AUTHORS
.. _tests/: https://github.com/scrapy/scrapy/tree/master/tests

View File

@ -21,7 +21,7 @@ Python code.
In other words, comparing `BeautifulSoup`_ (or `lxml`_) to Scrapy is like
comparing `jinja2`_ to `Django`_.
.. _BeautifulSoup: http://www.crummy.com/software/BeautifulSoup/
.. _BeautifulSoup: https://www.crummy.com/software/BeautifulSoup/
.. _lxml: http://lxml.de/
.. _jinja2: http://jinja.pocoo.org/
.. _Django: https://www.djangoproject.com/
@ -69,9 +69,11 @@ Here's an example spider using BeautifulSoup API, with ``lxml`` as the HTML pars
What Python versions does Scrapy support?
-----------------------------------------
Scrapy is supported under Python 2.7 and Python 3.3+.
Scrapy is supported under Python 2.7 and Python 3.4+
under CPython (default Python implementation) and PyPy (starting with PyPy 5.9).
Python 2.6 support was dropped starting at Scrapy 0.20.
Python 3 support was added in Scrapy 1.1.
PyPy support was added in Scrapy 1.4, PyPy3 support was added in Scrapy 1.5.
.. note::
For Python 3 support on Windows, it is recommended to use

View File

@ -7,7 +7,8 @@ Installation guide
Installing Scrapy
=================
Scrapy runs on Python 2.7 and Python 3.3 or above.
Scrapy runs on Python 2.7 and Python 3.4 or above
under CPython (default Python implementation) and PyPy (starting with PyPy 5.9).
If you're using `Anaconda`_ or `Miniconda`_, you can install the package from
the `conda-forge`_ channel, which has up-to-date packages for Linux, Windows
@ -132,12 +133,12 @@ Once you've installed `Anaconda`_ or `Miniconda`_, install Scrapy with::
.. _intro-install-ubuntu:
Ubuntu 12.04 or above
Ubuntu 14.04 or above
---------------------
Scrapy is currently tested with recent-enough versions of lxml,
twisted and pyOpenSSL, and is compatible with recent Ubuntu distributions.
But it should support older versions of Ubuntu too, like Ubuntu 12.04,
But it should support older versions of Ubuntu too, like Ubuntu 14.04,
albeit with potential issues with TLS connections.
**Don't** use the ``python-scrapy`` package provided by Ubuntu, they are
@ -163,8 +164,8 @@ you can install Scrapy with ``pip`` after that::
pip install scrapy
.. note::
The same non-python dependencies can be used to install Scrapy in Debian
Wheezy (7.0) and above.
The same non-Python dependencies can be used to install Scrapy in Debian
Jessie (8.0) and above.
.. _intro-install-macos:
@ -188,7 +189,7 @@ solutions:
that doesn't conflict with the rest of your system. Here's how to do it using
the `homebrew`_ package manager:
* Install `homebrew`_ following the instructions in http://brew.sh/
* Install `homebrew`_ following the instructions in https://brew.sh/
* Update your ``PATH`` variable to state that homebrew packages should be
used before system packages (Change ``.bashrc`` to ``.zshrc`` accordantly
@ -223,6 +224,29 @@ After any of these workarounds you should be able to install Scrapy::
pip install Scrapy
PyPy
----
We recommend using the latest PyPy version. The version tested is 5.9.0.
For PyPy3, only Linux installation was tested.
Most scrapy dependencides now have binary wheels for CPython, but not for PyPy.
This means that these dependecies will be built during installation.
On OS X, you are likely to face an issue with building Cryptography dependency,
solution to this problem is described
`here <https://github.com/pyca/cryptography/issues/2692#issuecomment-272773481>`_,
that is to ``brew install openssl`` and then export the flags that this command
recommends (only needed when installing scrapy). Installing on Linux has no special
issues besides installing build dependencies.
Installing scrapy with PyPy on Windows is not tested.
You can check that scrapy is installed correctly by running ``scrapy bench``.
If this command gives errors such as
``TypeError: ... got 2 unexpected keyword arguments``, this means
that setuptools was unable to pick up one PyPy-specific dependency.
To fix this issue, run ``pip install 'PyPyDispatcher>=2.1.0'``.
.. _Python: https://www.python.org/
.. _pip: https://pip.pypa.io/en/latest/installing/
.. _lxml: http://lxml.de/
@ -233,9 +257,9 @@ After any of these workarounds you should be able to install Scrapy::
.. _pyOpenSSL: https://pypi.python.org/pypi/pyOpenSSL
.. _setuptools: https://pypi.python.org/pypi/setuptools
.. _AUR Scrapy package: https://aur.archlinux.org/packages/scrapy/
.. _homebrew: http://brew.sh/
.. _zsh: http://www.zsh.org/
.. _Scrapinghub: http://scrapinghub.com
.. _Anaconda: http://docs.continuum.io/anaconda/index
.. _Miniconda: http://conda.pydata.org/docs/install/quick.html
.. _conda-forge: https://conda-forge.github.io/
.. _homebrew: https://brew.sh/
.. _zsh: https://www.zsh.org/
.. _Scrapinghub: https://scrapinghub.com
.. _Anaconda: https://docs.anaconda.com/anaconda/
.. _Miniconda: https://conda.io/docs/user-guide/install/index.html
.. _conda-forge: https://conda-forge.org/

View File

@ -160,8 +160,8 @@ The next steps for you are to :ref:`install Scrapy <intro-install>`,
a full-blown Scrapy project and `join the community`_. Thanks for your
interest!
.. _join the community: http://scrapy.org/community/
.. _join the community: https://scrapy.org/community/
.. _web scraping: https://en.wikipedia.org/wiki/Web_scraping
.. _Amazon Associates Web Services: https://affiliate-program.amazon.com/gp/advertising/api/detail/main.html
.. _Amazon S3: https://aws.amazon.com/s3/
.. _Sitemaps: http://www.sitemaps.org
.. _Sitemaps: https://www.sitemaps.org/index.html

View File

@ -34,7 +34,7 @@ list of Python resources for non-programmers`_.
.. _this list of Python resources for non-programmers: https://wiki.python.org/moin/BeginnersGuide/NonProgrammers
.. _Dive Into Python 3: http://www.diveintopython3.net
.. _Python Tutorial: https://docs.python.org/3/tutorial
.. _Learn Python The Hard Way: http://learnpythonthehardway.org/book/
.. _Learn Python The Hard Way: https://learnpythonthehardway.org/book/
Creating a project
@ -54,6 +54,8 @@ This will create a ``tutorial`` directory with the following contents::
__init__.py
items.py # project items definition file
middlewares.py # project middlewares file
pipelines.py # project pipelines file
@ -452,7 +454,7 @@ For historic reasons, Scrapy appends to a given file instead of overwriting
its contents. If you run this command twice without removing the file
before the second time, you'll end up with a broken JSON file.
You can also used other formats, like `JSON Lines`_::
You can also use other formats, like `JSON Lines`_::
scrapy crawl quotes -o quotes.jl

View File

@ -3,6 +3,143 @@
Release notes
=============
Scrapy 1.6.0 (unreleased)
-------------------------
Cleanups
~~~~~~~~
* Remove deprecated ``CrawlerSettings`` class.
* Remove deprecated ``Settings.overrides`` and ``Settings.defaults`` attributes.
Scrapy 1.5.1 (2018-07-12)
-------------------------
This is a maintenance release with important bug fixes, but no new features:
* ``O(N^2)`` gzip decompression issue which affected Python 3 and PyPy
is fixed (:issue:`3281`);
* skipping of TLS validation errors is improved (:issue:`3166`);
* Ctrl-C handling is fixed in Python 3.5+ (:issue:`3096`);
* testing fixes (:issue:`3092`, :issue:`3263`);
* documentation improvements (:issue:`3058`, :issue:`3059`, :issue:`3089`,
:issue:`3123`, :issue:`3127`, :issue:`3189`, :issue:`3224`, :issue:`3280`,
:issue:`3279`, :issue:`3201`, :issue:`3260`, :issue:`3284`, :issue:`3298`,
:issue:`3294`).
Scrapy 1.5.0 (2017-12-29)
-------------------------
This release brings small new features and improvements across the codebase.
Some highlights:
* Google Cloud Storage is supported in FilesPipeline and ImagesPipeline.
* Crawling with proxy servers becomes more efficient, as connections
to proxies can be reused now.
* Warnings, exception and logging messages are improved to make debugging
easier.
* ``scrapy parse`` command now allows to set custom request meta via
``--meta`` argument.
* Compatibility with Python 3.6, PyPy and PyPy3 is improved;
PyPy and PyPy3 are now supported officially, by running tests on CI.
* Better default handling of HTTP 308, 522 and 524 status codes.
* Documentation is improved, as usual.
Backwards Incompatible Changes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Scrapy 1.5 drops support for Python 3.3.
* Default Scrapy User-Agent now uses https link to scrapy.org (:issue:`2983`).
**This is technically backwards-incompatible**; override
:setting:`USER_AGENT` if you relied on old value.
* Logging of settings overridden by ``custom_settings`` is fixed;
**this is technically backwards-incompatible** because the logger
changes from ``[scrapy.utils.log]`` to ``[scrapy.crawler]``. If you're
parsing Scrapy logs, please update your log parsers (:issue:`1343`).
* LinkExtractor now ignores ``m4v`` extension by default, this is change
in behavior.
* 522 and 524 status codes are added to ``RETRY_HTTP_CODES`` (:issue:`2851`)
New features
~~~~~~~~~~~~
- Support ``<link>`` tags in ``Response.follow`` (:issue:`2785`)
- Support for ``ptpython`` REPL (:issue:`2654`)
- Google Cloud Storage support for FilesPipeline and ImagesPipeline
(:issue:`2923`).
- New ``--meta`` option of the "scrapy parse" command allows to pass additional
request.meta (:issue:`2883`)
- Populate spider variable when using ``shell.inspect_response`` (:issue:`2812`)
- Handle HTTP 308 Permanent Redirect (:issue:`2844`)
- Add 522 and 524 to ``RETRY_HTTP_CODES`` (:issue:`2851`)
- Log versions information at startup (:issue:`2857`)
- ``scrapy.mail.MailSender`` now works in Python 3 (it requires Twisted 17.9.0)
- Connections to proxy servers are reused (:issue:`2743`)
- Add template for a downloader middleware (:issue:`2755`)
- Explicit message for NotImplementedError when parse callback not defined
(:issue:`2831`)
- CrawlerProcess got an option to disable installation of root log handler
(:issue:`2921`)
- LinkExtractor now ignores ``m4v`` extension by default
- Better log messages for responses over :setting:`DOWNLOAD_WARNSIZE` and
:setting:`DOWNLOAD_MAXSIZE` limits (:issue:`2927`)
- Show warning when a URL is put to ``Spider.allowed_domains`` instead of
a domain (:issue:`2250`).
Bug fixes
~~~~~~~~~
- Fix logging of settings overridden by ``custom_settings``;
**this is technically backwards-incompatible** because the logger
changes from ``[scrapy.utils.log]`` to ``[scrapy.crawler]``, so please
update your log parsers if needed (:issue:`1343`)
- Default Scrapy User-Agent now uses https link to scrapy.org (:issue:`2983`).
**This is technically backwards-incompatible**; override
:setting:`USER_AGENT` if you relied on old value.
- Fix PyPy and PyPy3 test failures, support them officially
(:issue:`2793`, :issue:`2935`, :issue:`2990`, :issue:`3050`, :issue:`2213`,
:issue:`3048`)
- Fix DNS resolver when ``DNSCACHE_ENABLED=False`` (:issue:`2811`)
- Add ``cryptography`` for Debian Jessie tox test env (:issue:`2848`)
- Add verification to check if Request callback is callable (:issue:`2766`)
- Port ``extras/qpsclient.py`` to Python 3 (:issue:`2849`)
- Use getfullargspec under the scenes for Python 3 to stop DeprecationWarning
(:issue:`2862`)
- Update deprecated test aliases (:issue:`2876`)
- Fix ``SitemapSpider`` support for alternate links (:issue:`2853`)
Docs
~~~~
- Added missing bullet point for the ``AUTOTHROTTLE_TARGET_CONCURRENCY``
setting. (:issue:`2756`)
- Update Contributing docs, document new support channels
(:issue:`2762`, issue:`3038`)
- Include references to Scrapy subreddit in the docs
- Fix broken links; use https:// for external links
(:issue:`2978`, :issue:`2982`, :issue:`2958`)
- Document CloseSpider extension better (:issue:`2759`)
- Use ``pymongo.collection.Collection.insert_one()`` in MongoDB example
(:issue:`2781`)
- Spelling mistake and typos
(:issue:`2828`, :issue:`2837`, :issue:`2884`, :issue:`2924`)
- Clarify ``CSVFeedSpider.headers`` documentation (:issue:`2826`)
- Document ``DontCloseSpider`` exception and clarify ``spider_idle``
(:issue:`2791`)
- Update "Releases" section in README (:issue:`2764`)
- Fix rst syntax in ``DOWNLOAD_FAIL_ON_DATALOSS`` docs (:issue:`2763`)
- Small fix in description of startproject arguments (:issue:`2866`)
- Clarify data types in Response.body docs (:issue:`2922`)
- Add a note about ``request.meta['depth']`` to DepthMiddleware docs (:issue:`2374`)
- Add a note about ``request.meta['dont_merge_cookies']`` to CookiesMiddleware
docs (:issue:`2999`)
- Up-to-date example of project structure (:issue:`2964`, :issue:`2976`)
- A better example of ItemExporters usage (:issue:`2989`)
- Document ``from_crawler`` methods for spider and downloader middlewares
(:issue:`3019`)
Scrapy 1.4.0 (2017-05-18)
-------------------------
@ -44,7 +181,7 @@ attributes with ``FormRequest``.
**Please also note that link extractors do not canonicalize URLs by default
anymore.** This was puzzling users every now and then, and it's not what
browsers do in fact, so we removed that extra transformation on extractred
browsers do in fact, so we removed that extra transformation on extracted
links.
For those of you wanting more control on the ``Referer:`` header that Scrapy

View File

@ -1,2 +1,2 @@
Sphinx>=1.3
Sphinx>=1.6
sphinx_rtd_theme

View File

@ -20,7 +20,7 @@ These are some common properties often found in broad crawls:
* they crawl many domains (often, unbounded) instead of a specific set of sites
* they don't necessarily crawl domains to completion, because it would
* they don't necessarily crawl domains to completion, because it would be
impractical (or impossible) to do so, and instead limit the crawl by time or
number of pages crawled

View File

@ -55,6 +55,7 @@ structure by default, similar to this::
myproject/
__init__.py
items.py
middlewares.py
pipelines.py
settings.py
spiders/
@ -187,7 +188,7 @@ startproject
Creates a new Scrapy project named ``project_name``, under the ``project_dir``
directory.
If ``project_dir`` wasn't specified, ``project_dir`` will be the same as ``myproject``.
If ``project_dir`` wasn't specified, ``project_dir`` will be the same as ``project_name``.
Usage example::
@ -430,6 +431,9 @@ Supported options:
* ``--callback`` or ``-c``: spider method to use as callback for parsing the
response
* ``--meta`` or ``-m``: additional request meta that will be passed to the callback
request. This must be a valid json string. Example: --meta='{"foo" : "bar"}'
* ``--pipelines``: process items through pipelines
* ``--rules`` or ``-r``: use :class:`~scrapy.spiders.CrawlSpider`

View File

@ -142,4 +142,4 @@ available in all future runs should they be necessary again::
For more information, check the :ref:`topics-logging` section.
.. _base tag: http://www.w3schools.com/tags/tag_base.asp
.. _base tag: https://www.w3schools.com/tags/tag_base.asp

View File

@ -51,9 +51,9 @@ just like ``scrapyd-deploy``.
.. _Scrapyd: https://github.com/scrapy/scrapyd
.. _Deploying your project: https://scrapyd.readthedocs.io/en/latest/deploy.html
.. _Scrapy Cloud: http://scrapinghub.com/scrapy-cloud/
.. _Scrapy Cloud: https://scrapinghub.com/scrapy-cloud
.. _scrapyd-client: https://github.com/scrapy/scrapyd-client
.. _shub: http://doc.scrapinghub.com/shub.html
.. _shub: https://doc.scrapinghub.com/shub.html
.. _scrapyd-deploy documentation: https://scrapyd.readthedocs.io/en/latest/deploy.html
.. _Scrapy Cloud documentation: http://doc.scrapinghub.com/scrapy-cloud.html
.. _Scrapinghub: http://scrapinghub.com/
.. _Scrapy Cloud documentation: https://doc.scrapinghub.com/scrapy-cloud.html
.. _Scrapinghub: https://scrapinghub.com/

View File

@ -157,6 +157,17 @@ more of the following methods:
:param spider: the spider for which this request is intended
:type spider: :class:`~scrapy.spiders.Spider` object
.. method:: from_crawler(cls, crawler)
If present, this classmethod is called to create a middleware instance
from a :class:`~scrapy.crawler.Crawler`. It must return a new instance
of the middleware. Crawler object provides access to all Scrapy core
components like settings and signals; it is a way for middleware to
access them and hook its functionality into Scrapy.
:param crawler: crawler that uses this middleware
:type crawler: :class:`~scrapy.crawler.Crawler` object
.. _topics-downloader-middleware-ref:
Built-in downloader middleware reference
@ -226,6 +237,15 @@ Default: ``True``
Whether to enable the cookies middleware. If disabled, no cookies will be sent
to web servers.
Notice that despite the value of :setting:`COOKIES_ENABLED` setting if
``Request.``:reqmeta:`meta['dont_merge_cookies'] <dont_merge_cookies>`
evaluates to ``True`` the request cookies will **not** be sent to the
web server and received cookies in :class:`~scrapy.http.Response` will
**not** be merged with the existing cookies.
For more detailed information see the ``cookies`` parameter in
:class:`~scrapy.http.Request`.
.. setting:: COOKIES_DEBUG
COOKIES_DEBUG
@ -862,7 +882,7 @@ precedence over the :setting:`RETRY_TIMES` setting.
RETRY_HTTP_CODES
^^^^^^^^^^^^^^^^
Default: ``[500, 502, 503, 504, 408]``
Default: ``[500, 502, 503, 504, 522, 524, 408]``
Which HTTP response codes to retry. Other errors (DNS lookup issues,
connections lost, etc) are always retried.

View File

@ -54,10 +54,10 @@ uses `Twisted non-blocking IO`_, like the rest of the framework.
:param smtpuser: the SMTP user. If omitted, the :setting:`MAIL_USER`
setting will be used. If not given, no SMTP authentication will be
performed.
:type smtphost: str
:type smtphost: str or bytes
:param smtppass: the SMTP pass for authentication.
:type smtppass: str
:type smtppass: str or bytes
:param smtpport: the SMTP port to connect to
:type smtpport: int

View File

@ -36,38 +36,36 @@ to export
3. and finally call the :meth:`~BaseItemExporter.finish_exporting` to signal
the end of the exporting process
Here you can see an :doc:`Item Pipeline <item-pipeline>` which uses an Item
Exporter to export scraped items to different files, one per spider::
Here you can see an :doc:`Item Pipeline <item-pipeline>` which uses multiple
Item Exporters to group scraped items to different files according to the
value of one of their fields::
from scrapy import signals
from scrapy.exporters import XmlItemExporter
from scrapy.exporters import XmlItemExporter
class XmlExportPipeline(object):
class PerYearXmlExportPipeline(object):
"""Distribute items across multiple XML files according to their 'year' field"""
def __init__(self):
self.files = {}
def open_spider(self, spider):
self.year_to_exporter = {}
@classmethod
def from_crawler(cls, crawler):
pipeline = cls()
crawler.signals.connect(pipeline.spider_opened, signals.spider_opened)
crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)
return pipeline
def close_spider(self, spider):
for exporter in self.year_to_exporter.values():
exporter.finish_exporting()
exporter.file.close()
def spider_opened(self, spider):
file = open('%s_products.xml' % spider.name, 'w+b')
self.files[spider] = file
self.exporter = XmlItemExporter(file)
self.exporter.start_exporting()
def _exporter_for_item(self, item):
year = item['year']
if year not in self.year_to_exporter:
f = open('{}.xml'.format(year), 'wb')
exporter = XmlItemExporter(f)
exporter.start_exporting()
self.year_to_exporter[year] = exporter
return self.year_to_exporter[year]
def spider_closed(self, spider):
self.exporter.finish_exporting()
file = self.files.pop(spider)
file.close()
def process_item(self, item, spider):
self.exporter.export_item(item)
return item
def process_item(self, item, spider):
exporter = self._exporter_for_item(item)
exporter.export_item(item)
return item
.. _topics-exporters-field-serialization:

View File

@ -280,7 +280,7 @@ An integer which specifies a number of items. If the spider scrapes more than
that amount and those items are passed by the item pipeline, the
spider will be closed with the reason ``closespider_itemcount``.
Requests which are currently in the downloader queue (up to
:setting:`CONCURRENT_REQUESTS` requests) are still processed.
:setting:`CONCURRENT_REQUESTS` requests) are still processed.
If zero (or non set), spiders won't be closed by number of passed items.
.. setting:: CLOSESPIDER_PAGECOUNT
@ -373,4 +373,4 @@ For more info see `Debugging in Python`.
This extension only works on POSIX-compliant platforms (ie. not Windows).
.. _Python debugger: https://docs.python.org/2/library/pdb.html
.. _Debugging in Python: http://www.ferg.org/papers/debugging_in_python.html
.. _Debugging in Python: https://pythonconquerstheuniverse.wordpress.com/2009/09/10/debugging-in-python/

View File

@ -177,7 +177,7 @@ The feeds are stored on `Amazon S3`_.
* ``s3://mybucket/path/to/export.csv``
* ``s3://aws_key:aws_secret@mybucket/path/to/export.csv``
* Required external libraries: `botocore`_ or `boto`_
* Required external libraries: `botocore`_ (Python 2 and Python 3) or `boto`_ (Python 2 only)
The AWS credentials can be passed as user/password in the URI, or they can be
passed through the following settings:

View File

@ -23,7 +23,7 @@ In this example, we'll show how to use `Firebug`_ to scrape data from the
Project`_ used in the :ref:`tutorial <intro-tutorial>` but with a different
face.
.. _Firebug: http://getfirebug.com
.. _Firebug: https://getfirebug.com/
.. _Google Directory: http://directory.google.com/
.. _Open Directory Project: http://www.dmoz.org

View File

@ -17,7 +17,7 @@ when inspecting the page source is not the original HTML, but a modified one
after applying some browser clean up and executing Javascript code. Firefox,
in particular, is known for adding ``<tbody>`` elements to tables. Scrapy, on
the other hand, does not modify the original page HTML, so you won't be able to
extract any data if you use ``<tbody>`` in your XPath expressions.
extract any data if you use ``<tbody>`` in your XPath expressions.
Therefore, you should keep in mind the following things when working with
Firefox and XPath:
@ -71,11 +71,11 @@ Firecookie
`Firecookie`_ makes it easier to view and manage cookies. You can use this
extension to create a new cookie, delete existing cookies, see a list of cookies
for the current site, manage cookies permissions and a lot more.
for the current site, manage cookies permissions and a lot more.
.. _Firebug: http://getfirebug.com
.. _Firebug: https://getfirebug.com/
.. _Inspect Element: https://www.youtube.com/watch?v=-pT_pDe54aA
.. _XPather: https://addons.mozilla.org/en-US/firefox/addon/xpather/
.. _XPather: https://addons.mozilla.org/en-US/firefox/addon/xpather/
.. _XPath Checker: https://addons.mozilla.org/en-US/firefox/addon/xpath-checker/
.. _Tamper Data: https://addons.mozilla.org/en-US/firefox/addon/tamper-data/
.. _Firecookie: https://addons.mozilla.org/en-US/firefox/addon/firecookie/

View File

@ -100,4 +100,4 @@ If you wish to log the requests that couldn't be serialized, you can set the
:setting:`SCHEDULER_DEBUG` setting to ``True`` in the project's settings page.
It is ``False`` by default.
.. _pickle: http://docs.python.org/library/pickle.html
.. _pickle: https://docs.python.org/library/pickle.html

View File

@ -202,6 +202,7 @@ memory leaks (Requests, Responses, Items, and Selectors). However, there are
other cases where the memory leaks could come from other (more or less obscure)
objects. If this is your case, and you can't find your leaks using ``trackref``,
you still have another resource: the `Guppy library`_.
If you're using Python3, see :ref:`topics-leaks-muppy`.
.. _Guppy library: https://pypi.python.org/pypi/guppy
@ -253,6 +254,50 @@ knowledge about Python internals. For more info about Guppy, refer to the
.. _Guppy documentation: http://guppy-pe.sourceforge.net/
.. _topics-leaks-muppy:
Debugging memory leaks with muppy
=================================
If you're using Python 3, you can use muppy from `Pympler`_.
.. _Pympler: https://pypi.org/project/Pympler/
If you use ``pip``, you can install muppy with the following command::
pip install Pympler
Here's an example to view all Python objects available in
the heap using muppy::
>>> from pympler import muppy
>>> all_objects = muppy.get_objects()
>>> len(all_objects)
28667
>>> from pympler import summary
>>> suml = summary.summarize(all_objects)
>>> summary.print_(suml)
types | # objects | total size
==================================== | =========== | ============
<class 'str | 9822 | 1.10 MB
<class 'dict | 1658 | 856.62 KB
<class 'type | 436 | 443.60 KB
<class 'code | 2974 | 419.56 KB
<class '_io.BufferedWriter | 2 | 256.34 KB
<class 'set | 420 | 159.88 KB
<class '_io.BufferedReader | 1 | 128.17 KB
<class 'wrapper_descriptor | 1130 | 88.28 KB
<class 'tuple | 1304 | 86.57 KB
<class 'weakref | 1013 | 79.14 KB
<class 'builtin_function_or_method | 958 | 67.36 KB
<class 'method_descriptor | 865 | 60.82 KB
<class 'abc.ABCMeta | 62 | 59.96 KB
<class 'list | 446 | 58.52 KB
<class 'int | 1425 | 43.20 KB
For more info about muppy, refer to the `muppy documentation`_.
.. _muppy documentation: https://pythonhosted.org/Pympler/muppy.html
.. _topics-leaks-without-leaks:
Leaks without leaks

View File

@ -136,6 +136,20 @@ accept one (and only one) positional argument, which will be an iterator.
containing the collected values (for that field). The result of the output
processors is the value that will be finally assigned to the item.
If you want to use a plain function as a processor, make sure it receives
``self`` as the first argument::
def lowercase_processor(self, values):
for v in values:
yield v.lower()
class MyItemLoader(ItemLoader):
name_in = lowercase_processor
This is because whenever a function is assigned as a class variable, it becomes
a method and would be passed the instance as the the first argument when being
called. See `this answer on stackoverflow`_ for more details.
The other thing you need to keep in mind is that the values returned by input
processors are collected internally (in lists) and then passed to output
processors to populate the fields.
@ -143,6 +157,7 @@ processors to populate the fields.
Last, but not least, Scrapy comes with some :ref:`commonly used processors
<topics-loaders-available-processors>` built-in for convenience.
.. _this answer on stackoverflow: https://stackoverflow.com/a/35322635
Declaring Item Loaders
======================
@ -518,8 +533,8 @@ a footer of a page that looks something like:
Example::
<footer>
<a class="social" href="http://facebook.com/whatever">Like Us</a>
<a class="social" href="http://twitter.com/whatever">Follow Us</a>
<a class="social" href="https://facebook.com/whatever">Like Us</a>
<a class="social" href="https://twitter.com/whatever">Follow Us</a>
<a class="email" href="mailto:whatever@example.com">Email Us</a>
</footer>

View File

@ -102,7 +102,7 @@ instance, which can be accessed and used like this::
class MySpider(scrapy.Spider):
name = 'myspider'
start_urls = ['http://scrapinghub.com']
start_urls = ['https://scrapinghub.com']
def parse(self, response):
self.logger.info('Parse function called on %s', response.url)
@ -118,7 +118,7 @@ Python logger you want. For example::
class MySpider(scrapy.Spider):
name = 'myspider'
start_urls = ['http://scrapinghub.com']
start_urls = ['https://scrapinghub.com']
def parse(self, response):
logger.info('Parse function called on %s', response.url)

View File

@ -15,7 +15,8 @@ typically you'll either use the Files Pipeline or the Images Pipeline.
Both pipelines implement these features:
* Avoid re-downloading media that was downloaded recently
* Specifying where to store the media (filesystem directory, Amazon S3 bucket)
* Specifying where to store the media (filesystem directory, Amazon S3 bucket,
Google Cloud Storage bucket)
The Images Pipeline has a few extra functions for processing images:
@ -116,10 +117,11 @@ For the Images Pipeline, set the :setting:`IMAGES_STORE` setting::
Supported Storage
=================
File system is currently the only officially supported storage, but there is
also support for storing files in `Amazon S3`_.
File system is currently the only officially supported storage, but there are
also support for storing files in `Amazon S3`_ and `Google Cloud Storage`_.
.. _Amazon S3: https://aws.amazon.com/s3/
.. _Google Cloud Storage: https://cloud.google.com/storage/
File system storage
-------------------
@ -169,7 +171,53 @@ policy::
For more information, see `canned ACLs`_ in the Amazon S3 Developer Guide.
.. _canned ACLs: http://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl
Because Scrapy uses ``boto`` / ``botocore`` internally you can also use other S3-like storages. Storages like
self-hosted `Minio`_ or `s3.scality`_. All you need to do is set endpoint option in you Scrapy settings::
AWS_ENDPOINT_URL = 'http://minio.example.com:9000'
For self-hosting you also might feel the need not to use SSL and not to verify SSL connection::
AWS_USE_SSL = False # or True (None by default)
AWS_VERIFY = False # or True (None by default)
.. _Minio: https://github.com/minio/minio
.. _s3.scality: https://s3.scality.com/
.. _canned ACLs: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl
Google Cloud Storage
---------------------
.. setting:: GCS_PROJECT_ID
.. setting:: FILES_STORE_GCS_ACL
.. setting:: IMAGES_STORE_GCS_ACL
:setting:`FILES_STORE` and :setting:`IMAGES_STORE` can represent a Google Cloud Storage
bucket. Scrapy will automatically upload the files to the bucket. (requires `google-cloud-storage`_ )
.. _google-cloud-storage: https://cloud.google.com/storage/docs/reference/libraries#client-libraries-install-python
For example, these are valid :setting:`IMAGES_STORE` and :setting:`GCS_PROJECT_ID` settings::
IMAGES_STORE = 'gs://bucket/images/'
GCS_PROJECT_ID = 'project_id'
For information about authentication, see this `documentation`_.
.. _documentation: https://cloud.google.com/docs/authentication/production
You can modify the Access Control List (ACL) policy used for the stored files,
which is defined by the :setting:`FILES_STORE_GCS_ACL` and
:setting:`IMAGES_STORE_GCS_ACL` settings. By default, the ACL is set to
``''`` (empty string) which means that Cloud Storage applies the bucket's default object ACL to the object.
To make the files publicly available use the ``publicRead``
policy::
IMAGES_STORE_GCS_ACL = 'publicRead'
For more information, see `Predefined ACLs`_ in the Google Cloud Platform Developer Guide.
.. _Predefined ACLs: https://cloud.google.com/storage/docs/access-control/lists#predefined-acl
Usage example
=============

View File

@ -248,10 +248,10 @@ If you are still unable to prevent your bot getting banned, consider contacting
`commercial support`_.
.. _Tor project: https://www.torproject.org/
.. _commercial support: http://scrapy.org/support/
.. _ProxyMesh: http://proxymesh.com/
.. _commercial support: https://scrapy.org/support/
.. _ProxyMesh: https://proxymesh.com/
.. _Google cache: http://www.googleguide.com/cached_pages.html
.. _testspiders: https://github.com/scrapinghub/testspiders
.. _Twisted Reactor Overview: https://twistedmatrix.com/documents/current/core/howto/reactor-basics.html
.. _Crawlera: http://scrapinghub.com/crawlera
.. _scrapoxy: http://scrapoxy.io/
.. _Crawlera: https://scrapinghub.com/crawlera
.. _scrapoxy: https://scrapoxy.io/

View File

@ -80,6 +80,8 @@ Request objects
attributes of the cookie. This is only useful if the cookies are saved
for later requests.
.. reqmeta:: dont_merge_cookies
When some site returns cookies (in a response) those are stored in the
cookies for that domain and will be sent again in future requests. That's
the typical behaviour of any regular web browser. However, if, for some
@ -294,7 +296,7 @@ Those are:
* :reqmeta:`dont_retry`
* :reqmeta:`handle_httpstatus_list`
* :reqmeta:`handle_httpstatus_all`
* ``dont_merge_cookies`` (see ``cookies`` parameter of :class:`Request` constructor)
* :reqmeta:`dont_merge_cookies`
* :reqmeta:`cookiejar`
* :reqmeta:`dont_cache`
* :reqmeta:`redirect_urls`
@ -525,11 +527,11 @@ Response objects
(for single valued headers) or lists (for multi-valued headers).
:type headers: dict
:param body: the response body. It must be str, not unicode, unless you're
using a encoding-aware :ref:`Response subclass
<topics-request-response-ref-response-subclasses>`, such as
:class:`TextResponse`.
:type body: str
:param body: the response body. To access the decoded text as str (unicode
in Python 2) you can use ``response.text`` from an encoding-aware
:ref:`Response subclass <topics-request-response-ref-response-subclasses>`,
such as :class:`TextResponse`.
:type body: bytes
:param flags: is a list containing the initial values for the
:attr:`Response.flags` attribute. If given, the list will be shallow
@ -734,7 +736,7 @@ HtmlResponse objects
which adds encoding auto-discovering support by looking into the HTML `meta
http-equiv`_ attribute. See :attr:`TextResponse.encoding`.
.. _meta http-equiv: http://www.w3schools.com/TAGS/att_meta_http_equiv.asp
.. _meta http-equiv: https://www.w3schools.com/TAGS/att_meta_http_equiv.asp
XmlResponse objects
-------------------

View File

@ -36,7 +36,7 @@ documents.
For a complete reference of the selectors API see
:ref:`Selector reference <topics-selectors-ref>`
.. _BeautifulSoup: http://www.crummy.com/software/BeautifulSoup/
.. _BeautifulSoup: https://www.crummy.com/software/BeautifulSoup/
.. _lxml: http://lxml.de/
.. _ElementTree: https://docs.python.org/2/library/xml.etree.elementtree.html
.. _cssselect: https://pypi.python.org/pypi/cssselect/
@ -86,7 +86,7 @@ To explain how to use the selectors we'll use the `Scrapy shell` (which
provides interactive testing) and an example page located in the Scrapy
documentation server:
http://doc.scrapy.org/en/latest/_static/selectors-sample1.html
https://doc.scrapy.org/en/latest/_static/selectors-sample1.html
.. _topics-selectors-htmlcode:
@ -99,7 +99,7 @@ Here's its HTML code:
First, let's open the shell::
scrapy shell http://doc.scrapy.org/en/latest/_static/selectors-sample1.html
scrapy shell https://doc.scrapy.org/en/latest/_static/selectors-sample1.html
Then, after the shell loads, you'll have the response available as ``response``
shell variable, and its attached selector in ``response.selector`` attribute.

View File

@ -180,6 +180,34 @@ such as the :ref:`S3 feed storage backend <topics-feed-storage-s3>`.
.. setting:: BOT_NAME
AWS_ENDPOINT_URL
----------------
Default: ``None``
Endpoint URL used for S3-like self-hosted storage. Storage like Minio or s3.scality.
.. setting:: AWS_ENDPOINT_URL
AWS_USE_SSL
-----------
Default: ``None``
Use this option if you want to disable SSL connection for communication with S3 or S3-like storage.
By default SSL will be used.
.. setting:: AWS_USE_SSL
AWS_VERIFY
----------
Default: ``None``
Verify SSL connection between Scrapy and S3 or S3-like storage. By default SSL verification will occur.
.. setting:: AWS_VERIFY
BOT_NAME
--------
@ -307,17 +335,6 @@ See also: :ref:`faq-bfo-dfo` about tuning Scrapy for BFO or DFO.
other priority settings :setting:`REDIRECT_PRIORITY_ADJUST`
and :setting:`RETRY_PRIORITY_ADJUST`.
.. setting:: DEPTH_STATS
DEPTH_STATS
-----------
Default: ``True``
Scope: ``scrapy.spidermiddlewares.depth.DepthMiddleware``
Whether to collect maximum depth stats.
.. setting:: DEPTH_STATS_VERBOSE
DEPTH_STATS_VERBOSE
@ -1002,7 +1019,7 @@ The randomization policy is the same used by `wget`_ ``--random-wait`` option.
If :setting:`DOWNLOAD_DELAY` is zero (default) this option has no effect.
.. _wget: http://www.gnu.org/software/wget/manual/wget.html
.. _wget: https://www.gnu.org/software/wget/manual/wget.html
.. setting:: REACTOR_THREADPOOL_MAXSIZE
@ -1317,14 +1334,14 @@ Default: ``2083``
Scope: ``spidermiddlewares.urllength``
The maximum URL length to allow for crawled URLs. For more information about
the default value for this setting see: http://www.boutell.com/newfaq/misc/urllength.html
the default value for this setting see: https://boutell.com/newfaq/misc/urllength.html
.. setting:: USER_AGENT
USER_AGENT
----------
Default: ``"Scrapy/VERSION (+http://scrapy.org)"``
Default: ``"Scrapy/VERSION (+https://scrapy.org)"``
The default User-Agent to use when crawling, unless overridden.

View File

@ -39,9 +39,9 @@ variable; or by defining it in your :ref:`scrapy.cfg <topics-config-settings>`::
[settings]
shell = bpython
.. _IPython: http://ipython.org/
.. _IPython installation guide: http://ipython.org/install.html
.. _bpython: http://www.bpython-interpreter.org/
.. _IPython: https://ipython.org/
.. _IPython installation guide: https://ipython.org/install.html
.. _bpython: https://www.bpython-interpreter.org/
Launch the shell
================
@ -142,7 +142,7 @@ Example of shell session
========================
Here's an example of a typical shell session where we start by scraping the
http://scrapy.org page, and then proceed to scrape the https://reddit.com
https://scrapy.org page, and then proceed to scrape the https://reddit.com
page. Finally, we modify the (Reddit) request method to POST and re-fetch it
getting an error. We end the session by typing Ctrl-D (in Unix systems) or
Ctrl-Z in Windows.
@ -154,7 +154,7 @@ shell works.
First, we launch the shell::
scrapy shell 'http://scrapy.org' --nolog
scrapy shell 'https://scrapy.org' --nolog
Then, the shell fetches the URL (using the Scrapy downloader) and prints the
list of available objects and useful shortcuts (you'll notice that these lines
@ -164,7 +164,7 @@ all start with the ``[s]`` prefix)::
[s] scrapy scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s] crawler <scrapy.crawler.Crawler object at 0x7f07395dd690>
[s] item {}
[s] request <GET http://scrapy.org>
[s] request <GET https://scrapy.org>
[s] response <200 https://scrapy.org/>
[s] settings <scrapy.settings.Settings object at 0x7f07395dd710>
[s] spider <DefaultSpider 'default' at 0x7f0735891690>
@ -182,7 +182,7 @@ After that, we can start playing with the objects::
>>> response.xpath('//title/text()').extract_first()
'Scrapy | A Fast and Powerful Scraping and Web Crawling Framework'
>>> fetch("http://reddit.com")
>>> fetch("https://reddit.com")
>>> response.xpath('//title/text()').extract()
['reddit: the front page of the internet']

View File

@ -135,6 +135,29 @@ item_dropped
to be dropped
:type exception: :exc:`~scrapy.exceptions.DropItem` exception
item_error
------------
.. signal:: item_error
.. function:: item_error(item, response, spider, failure)
Sent when a :ref:`topics-item-pipeline` generates an error (ie. raises
an exception), except :exc:`~scrapy.exceptions.DropItem` exception.
This signal supports returning deferreds from their handlers.
:param item: the item dropped from the :ref:`topics-item-pipeline`
:type item: dict or :class:`~scrapy.item.Item` object
:param response: the response being processed when the exception was raised
:type response: :class:`~scrapy.http.Response` object
:param spider: the spider which raised the exception
:type spider: :class:`~scrapy.spiders.Spider` object
:param failure: the exception raised as a Twisted `Failure`_ object
:type failure: `Failure`_ object
spider_closed
-------------

View File

@ -116,7 +116,7 @@ following methods:
method (from other spider middleware) raises an exception.
:meth:`process_spider_exception` should return either ``None`` or an
iterable of :class:`~scrapy.http.Response`, dict or
iterable of :class:`~scrapy.http.Request`, dict or
:class:`~scrapy.item.Item` objects.
If it returns ``None``, Scrapy will continue processing this exception,
@ -164,6 +164,17 @@ following methods:
:param spider: the spider to whom the start requests belong
:type spider: :class:`~scrapy.spiders.Spider` object
.. method:: from_crawler(cls, crawler)
If present, this classmethod is called to create a middleware instance
from a :class:`~scrapy.crawler.Crawler`. It must return a new instance
of the middleware. Crawler object provides access to all Scrapy core
components like settings and signals; it is a way for middleware to
access them and hook its functionality into Scrapy.
:param crawler: crawler that uses this middleware
:type crawler: :class:`~scrapy.crawler.Crawler` object
.. _Exception: https://docs.python.org/2/library/exceptions.html#exceptions.Exception
@ -188,16 +199,21 @@ DepthMiddleware
.. class:: DepthMiddleware
DepthMiddleware is a scrape middleware used for tracking the depth of each
Request inside the site being scraped. It can be used to limit the maximum
depth to scrape or things like that.
DepthMiddleware is used for tracking the depth of each Request inside the
site being scraped. It works by setting `request.meta['depth'] = 0` whenever
there is no value previously set (usually just the first Request) and
incrementing it by 1 otherwise.
It can be used to limit the maximum depth to scrape, control Request
priority based on their depth, and things like that.
The :class:`DepthMiddleware` can be configured through the following
settings (see the settings documentation for more info):
* :setting:`DEPTH_LIMIT` - The maximum depth that will be allowed to
crawl for any site. If zero, no limit will be imposed.
* :setting:`DEPTH_STATS` - Whether to collect depth stats.
* :setting:`DEPTH_STATS_VERBOSE` - Whether to collect the number of
requests for each depth.
* :setting:`DEPTH_PRIORITY` - Whether to prioritize the requests based on
their depth.

View File

@ -88,7 +88,7 @@ scrapy.Spider
A list of URLs where the spider will begin to crawl from, when no
particular URLs are specified. So, the first pages downloaded will be those
listed here. The subsequent URLs will be generated successively from data
listed here. The subsequent :class:`~scrapy.http.Request` will be generated successively from data
contained in the start URLs.
.. attribute:: custom_settings
@ -751,8 +751,8 @@ Combine SitemapSpider with other sources of urls::
def parse_other(self, response):
pass # ... scrape other here ...
.. _Sitemaps: http://www.sitemaps.org
.. _Sitemap index files: http://www.sitemaps.org/protocol.html#index
.. _Sitemaps: https://www.sitemaps.org/index.html
.. _Sitemap index files: https://www.sitemaps.org/protocol.html#index
.. _robots.txt: http://www.robotstxt.org/
.. _TLD: https://en.wikipedia.org/wiki/Top-level_domain
.. _Scrapyd documentation: https://scrapyd.readthedocs.io/en/latest/

View File

@ -37,5 +37,5 @@ To use the packages:
.. warning:: `python-scrapy` is a different package provided by official debian
repositories, it's very outdated and it isn't supported by Scrapy team.
.. _Scrapinghub: http://scrapinghub.com/
.. _Scrapinghub: https://scrapinghub.com/
.. _GitHub repo: https://github.com/scrapy/scrapy

View File

@ -20,7 +20,7 @@ _filename = None
_contents = None
# A regex that matches standard linkcheck output lines
line_re = re.compile(ur'(.*)\:\d+\:\s\[(.*)\]\s(?:(.*)\sto\s(.*)|(.*))')
line_re = re.compile(u'(.*)\:\d+\:\s\[(.*)\]\s(?:(.*)\sto\s(.*)|(.*))')
# Read lines from the linkcheck output file
try:

View File

@ -1,6 +1,6 @@
# Run tests, generate coverage report and open it on a browser
#
# Requires: coverage 3.3 or above from http://pypi.python.org/pypi/coverage
# Requires: coverage 3.3 or above from https://pypi.python.org/pypi/coverage
coverage run --branch $(which trial) --reporter=text tests
coverage html -i

View File

@ -41,7 +41,7 @@ class QPSSpider(Spider):
slots = int(self.slots)
if slots > 1:
urls = [url.replace('localhost', '127.0.0.%d' % (x + 1)) for x in xrange(slots)]
urls = [url.replace('localhost', '127.0.0.%d' % (x + 1)) for x in range(slots)]
else:
urls = [url]

View File

@ -2,9 +2,9 @@ Twisted>=13.1.0
lxml
pyOpenSSL
cssselect>=0.9
w3lib>=1.17.0
queuelib
w3lib>=1.17.0
six>=1.5.2
PyDispatcher>=2.0.5
parsel>=1.4
service_identity
parsel>=1.1

View File

@ -1,7 +1,10 @@
Twisted >= 15.5.0
Twisted>=17.9.0
lxml>=3.2.4
pyOpenSSL>=0.13.1
cssselect>=0.9
queuelib>=1.1.1
w3lib>=1.17.0
six>=1.5.2
PyDispatcher>=2.0.5
parsel>=1.4
service_identity

View File

@ -1 +1 @@
1.4.0
1.5.0

View File

@ -4,12 +4,12 @@ from six.moves import copyreg
if sys.version_info[0] == 2:
from urlparse import urlparse
# workaround for http://bugs.python.org/issue7904 - Python < 2.7
# workaround for https://bugs.python.org/issue7904 - Python < 2.7
if urlparse('s3://bucket/key').netloc != 'bucket':
from urlparse import uses_netloc
uses_netloc.append('s3')
# workaround for http://bugs.python.org/issue9374 - Python < 2.7.4
# workaround for https://bugs.python.org/issue9374 - Python < 2.7.4
if urlparse('s3://bucket/key?key=value').query != 'key=value':
from urlparse import uses_query
uses_query.append('s3')

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.command` is deprecated, "
"use `scrapy.commands` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.commands import *

View File

@ -56,3 +56,6 @@ class Command(ScrapyCommand):
self.crawler_process.crawl(spname, **opts.spargs)
self.crawler_process.start()
if self.crawler_process.bootstrap_failed:
self.exitcode = 1

View File

@ -1,4 +1,5 @@
import sys, os
import sys
import os
from scrapy.commands import ScrapyCommand
from scrapy.exceptions import UsageError

View File

@ -1,4 +1,5 @@
from __future__ import print_function
import json
import logging
from w3lib.url import is_url
@ -48,6 +49,8 @@ class Command(ScrapyCommand):
help="use CrawlSpider rules to discover the callback")
parser.add_option("-c", "--callback", dest="callback",
help="use this callback for parsing, instead looking for a callback")
parser.add_option("-m", "--meta", dest="meta",
help="inject extra meta into the Request, it must be a valid raw json string")
parser.add_option("-d", "--depth", dest="depth", type="int", default=1,
help="maximum depth for parsing requests [default: %default]")
parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
@ -204,6 +207,10 @@ class Command(ScrapyCommand):
req.callback = callback
return requests
#update request meta if any extra meta was passed through the --meta/-m opts.
if opts.meta:
request.meta.update(opts.meta)
request.meta['_depth'] = 1
request.meta['_callback'] = request.callback
request.callback = callback
@ -211,11 +218,27 @@ class Command(ScrapyCommand):
def process_options(self, args, opts):
ScrapyCommand.process_options(self, args, opts)
self.process_spider_arguments(opts)
self.process_request_meta(opts)
def process_spider_arguments(self, opts):
try:
opts.spargs = arglist_to_dict(opts.spargs)
except ValueError:
raise UsageError("Invalid -a value, use -a NAME=VALUE", print_help=False)
def process_request_meta(self, opts):
if opts.meta:
try:
opts.meta = json.loads(opts.meta)
except ValueError:
raise UsageError("Invalid -m/--meta value, pass a valid json string to -m or --meta. " \
"Example: --meta='{\"foo\" : \"bar\"}'", print_help=False)
def run(self, args, opts):
# parse arguments
if not len(args) == 1 or not is_url(args[0]):

View File

@ -87,3 +87,6 @@ class Command(ScrapyCommand):
self.crawler_process.crawl(spidercls, **opts.spargs)
self.crawler_process.start()
if self.crawler_process.bootstrap_failed:
self.exitcode = 1

View File

@ -1,12 +1,8 @@
from __future__ import print_function
import sys
import platform
import twisted
import OpenSSL
import scrapy
from scrapy.commands import ScrapyCommand
from scrapy.utils.versions import scrapy_components_versions
class Command(ScrapyCommand):
@ -27,38 +23,11 @@ class Command(ScrapyCommand):
def run(self, args, opts):
if opts.verbose:
import cssselect
import parsel
import lxml.etree
import w3lib
lxml_version = ".".join(map(str, lxml.etree.LXML_VERSION))
libxml2_version = ".".join(map(str, lxml.etree.LIBXML_VERSION))
try:
w3lib_version = w3lib.__version__
except AttributeError:
w3lib_version = "<1.14.3"
print("Scrapy : %s" % scrapy.__version__)
print("lxml : %s" % lxml_version)
print("libxml2 : %s" % libxml2_version)
print("cssselect : %s" % cssselect.__version__)
print("parsel : %s" % parsel.__version__)
print("w3lib : %s" % w3lib_version)
print("Twisted : %s" % twisted.version.short())
print("Python : %s" % sys.version.replace("\n", "- "))
print("pyOpenSSL : %s" % self._get_openssl_version())
print("Platform : %s" % platform.platform())
versions = scrapy_components_versions()
width = max(len(n) for (n, _) in versions)
patt = "%-{}s : %s".format(width)
for name, version in versions:
print(patt % (name, version))
else:
print("Scrapy %s" % scrapy.__version__)
def _get_openssl_version(self):
try:
openssl = OpenSSL.SSL.SSLeay_version(OpenSSL.SSL.SSLEAY_VERSION)\
.decode('ascii', errors='replace')
# pyOpenSSL 0.12 does not expose openssl version
except AttributeError:
openssl = 'Unknown OpenSSL version'
return '{} ({})'.format(OpenSSL.version.__version__, openssl)

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.closespider` is deprecated, "
"use `scrapy.extensions.closespider` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.extensions.closespider import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.corestats` is deprecated, "
"use `scrapy.extensions.corestats` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.extensions.corestats import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.debug` is deprecated, "
"use `scrapy.extensions.debug` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.extensions.debug import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.ajaxcrawl` is deprecated, "
"use `scrapy.downloadermiddlewares.ajaxcrawl` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.ajaxcrawl import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.chunked` is deprecated, "
"use `scrapy.downloadermiddlewares.chunked` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.chunked import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.cookies` is deprecated, "
"use `scrapy.downloadermiddlewares.cookies` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.cookies import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.decompression` is deprecated, "
"use `scrapy.downloadermiddlewares.decompression` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.decompression import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.defaultheaders` is deprecated, "
"use `scrapy.downloadermiddlewares.defaultheaders` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.defaultheaders import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.downloadtimeout` is deprecated, "
"use `scrapy.downloadermiddlewares.downloadtimeout` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.downloadtimeout import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.httpauth` is deprecated, "
"use `scrapy.downloadermiddlewares.httpauth` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.httpauth import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.httpcache` is deprecated, "
"use `scrapy.downloadermiddlewares.httpcache` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.httpcache import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.httpcompression` is deprecated, "
"use `scrapy.downloadermiddlewares.httpcompression` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.httpcompression import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.httpproxy` is deprecated, "
"use `scrapy.downloadermiddlewares.httpproxy` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.httpproxy import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.redirect` is deprecated, "
"use `scrapy.downloadermiddlewares.redirect` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.redirect import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.retry` is deprecated, "
"use `scrapy.downloadermiddlewares.retry` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.retry import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.robotstxt` is deprecated, "
"use `scrapy.downloadermiddlewares.robotstxt` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.robotstxt import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.stats` is deprecated, "
"use `scrapy.downloadermiddlewares.stats` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.stats import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.downloadermiddleware.useragent` is deprecated, "
"use `scrapy.downloadermiddlewares.useragent` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.downloadermiddlewares.useragent import *

View File

@ -1,8 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.exporter` is deprecated, "
"use `scrapy.exporters` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.exporters import *
from scrapy.exporters import PythonItemExporter

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.feedexport` is deprecated, "
"use `scrapy.extensions.feedexport` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.extensions.feedexport import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.httpcache` is deprecated, "
"use `scrapy.extensions.httpcache` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.extensions.httpcache import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.linkextractors` is deprecated, "
"use `scrapy.linkextractors` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.linkextractors import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.linkextractors.htmlparser` is deprecated, "
"use `scrapy.linkextractors.htmlparser` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.linkextractors.htmlparser import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.linkextractors.lxmlhtml` is deprecated, "
"use `scrapy.linkextractors.lxmlhtml` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.linkextractors.lxmlhtml import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.linkextractors.regex` is deprecated, "
"use `scrapy.linkextractors.regex` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.linkextractors.regex import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.linkextractors.sgml` is deprecated, "
"use `scrapy.linkextractors.sgml` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.linkextractors.sgml import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.loader` is deprecated, "
"use `scrapy.loader` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.loader import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.loader.common` is deprecated, "
"use `scrapy.loader.common` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.loader.common import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.loader.processor` is deprecated, "
"use `scrapy.loader.processors` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.loader.processors import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.logstats` is deprecated, "
"use `scrapy.extensions.logstats` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.extensions.logstats import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.memdebug` is deprecated, "
"use `scrapy.extensions.memdebug` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.extensions.memdebug import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.memusage` is deprecated, "
"use `scrapy.extensions.memusage` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.extensions.memusage import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.pipeline` is deprecated, "
"use `scrapy.pipelines` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.pipelines import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.pipeline.files` is deprecated, "
"use `scrapy.pipelines.files` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.pipelines.files import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.pipeline.images` is deprecated, "
"use `scrapy.pipelines.images` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.pipelines.images import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.pipeline.media` is deprecated, "
"use `scrapy.pipelines.media` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.pipelines.media import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.spidermiddleware.depth` is deprecated, "
"use `scrapy.spidermiddlewares.depth` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.spidermiddlewares.depth import *

View File

@ -1,7 +0,0 @@
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn("Module `scrapy.contrib.spidermiddleware.httperror` is deprecated, "
"use `scrapy.spidermiddlewares.httperror` instead",
ScrapyDeprecationWarning, stacklevel=2)
from scrapy.spidermiddlewares.httperror import *

Some files were not shown because too many files have changed in this diff Show More